home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / termXPR.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  73KB  |  3,538 lines

  1. /*
  2. **    termXPR.c
  3. **
  4. **    External transfer protocol support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. //#define USE_THE_NEW_CODE
  13. //#define USE_QUICK_IO
  14.  
  15. #include "termGlobal.h"
  16.  
  17.     /* These variables keep the transferred bytes and transfer
  18.      * time in seconds.
  19.      */
  20.  
  21. STATIC LONG        ByteVal,
  22.                  ByteMax,
  23.                  TimeVal,
  24.                  TimeMax,
  25.  
  26.                 LastTimeDif,
  27.                 LastPercent;
  28.  
  29.     /* Transfer statistics. */
  30.  
  31. STATIC ULONG    CPS_Minimum,
  32.                 CPS_Maximum,
  33.                 CPS_Average,
  34.                 CPS_Current,
  35.                 CPS_Count,
  36.                 CPS_Last;
  37.  
  38. LONG            CPL_Min,
  39.                 CPL_Avg,
  40.                 CPL_Cur;
  41.  
  42.     /* The name of the file being transmitted, in case the
  43.      * `override transfer path' feature is enabled.
  44.      */
  45.  
  46. STATIC struct Buffer *CurrentFile;
  47.  
  48.     /* Yet another flag, this one determines whether we already told
  49.      * the user that the file we are currently processing will fit
  50.      * on the destination device.
  51.      */
  52.  
  53. STATIC BYTE    Alerted,
  54.             DontWorry,
  55.             TypeChecked,
  56.             ErrorNotified,
  57.             CarrierMessage;
  58.  
  59. STATIC UBYTE __far    RealName[MAX_FILENAME_LENGTH];
  60. STATIC ULONG        LastSeconds;
  61.  
  62.     /* PrintBox(LONG Box,LONG Line,STRPTR String,...):
  63.      *
  64.      *    Update the contents of a text box.
  65.      */
  66.  
  67. STATIC VOID __stdargs
  68. PrintBox(LONG Box,LONG Line,STRPTR String,...)
  69. {
  70.     UBYTE     LocalBuffer[256];
  71.     va_list     VarArgs;
  72.  
  73.     va_start(VarArgs,String);
  74.     VSPrintf(LocalBuffer,String,VarArgs);
  75.     va_end(VarArgs);
  76.  
  77.     LT_SetAttributes(TransferHandle,Box,
  78.         LABX_Index,    Line,
  79.         LABX_Text,    LocalBuffer,
  80.     TAG_DONE);
  81. }
  82.  
  83.     /* OpenTransferWindow():
  84.      *
  85.      *    Local routine to open the transfer window.
  86.      */
  87.  
  88. STATIC BYTE
  89. OpenTransferWindow(VOID)
  90. {
  91.         /* Block window input. */
  92.  
  93.     BlockWindows();
  94.  
  95.         /* Try to open the transfer window panel. */
  96.  
  97.     if(TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  98.     {
  99.             /* Supply the log text. */
  100.  
  101.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  102.  
  103.             /* Return success. */
  104.  
  105.         return(TRUE);
  106.     }
  107.     else
  108.     {
  109.             /* Re-enable window input. */
  110.  
  111.         ReleaseWindows();
  112.  
  113.             /* Return failure. */
  114.  
  115.         return(FALSE);
  116.     }
  117. }
  118.  
  119.     /* CheckAbort(BOOLEAN CheckCarrier):
  120.      *
  121.      *    Check for transfer abort.
  122.      */
  123.  
  124. STATIC LONG __regargs
  125. CheckAbort(BOOLEAN CheckCarrier)
  126. {
  127.     struct IntuiMessage    *Message;
  128.     ULONG                 MsgClass,
  129.                          MsgQualifier;
  130.     UWORD                 MsgCode;
  131.     struct Gadget        *MsgGadget;
  132.     struct Window        *MsgWindow;
  133.     LONG                 Result = 0;
  134.  
  135.         /* No window available for output? */
  136.  
  137.     if(!TransferWindow)
  138.     {
  139.         if(!OpenTransferWindow())
  140.             return(-1);
  141.     }
  142.  
  143.         /* Are we to check the carrier status? */
  144.  
  145.     if(CheckCarrier)
  146.     {
  147.             /* Return error if carrier is lost. */
  148.  
  149.         if(GetSerialStatus() & CIAF_COMCD)
  150.         {
  151.             if(!CarrierMessage)
  152.             {
  153.                 CarrierMessage = TRUE;
  154.  
  155.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  156.             }
  157.  
  158.             ObtainSemaphore(&OnlineSemaphore);
  159.  
  160.             if(Online)
  161.             {
  162.                 WasOnline    = Online;
  163.                 Online        = FALSE;
  164.             }
  165.  
  166.             ReleaseSemaphore(&OnlineSemaphore);
  167.  
  168.             TransferError = TRUE;
  169.  
  170.             return(-1);
  171.         }
  172.     }
  173.  
  174.         /* Process all incoming messages. */
  175.  
  176.     while(Message = (struct IntuiMessage *)GT_GetIMsg(TransferWindow -> UserPort))
  177.     {
  178.         MsgClass        = Message -> Class;
  179.         MsgQualifier    = Message -> Qualifier;
  180.         MsgCode            = Message -> Code;
  181.         MsgGadget        = (struct Gadget *)Message -> IAddress;
  182.         MsgWindow        = Message -> IDCMPWindow;
  183.  
  184.         GT_ReplyIMsg(Message);
  185.  
  186.         if(MsgWindow == TransferWindow)
  187.         {
  188.             if(!Result)
  189.             {
  190.                 LT_HandleInput(TransferHandle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  191.  
  192.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  193.                 {
  194.                     LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  195.  
  196.                     TransferAborted = TRUE;
  197.  
  198.                     Result = -1;
  199.                 }
  200.  
  201.                 if(MsgClass == IDCMP_GADGETUP)
  202.                 {
  203.                     switch(MsgGadget -> GadgetID)
  204.                     {
  205.                         case GAD_TRANSFER_ABORT:
  206.  
  207.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  208.  
  209.                             TransferAborted = TRUE;
  210.  
  211.                             Result = -1;
  212.  
  213.                             break;
  214.  
  215.                         case GAD_TRANSFER_SKIP:
  216.  
  217.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  218.  
  219.                             Result = 1;
  220.  
  221.                             break;
  222.  
  223.                         case GAD_TRANSFER_ABORT_FILE:
  224.  
  225.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_ABORTED_TXT));
  226.  
  227.                             Result = 2;
  228.  
  229.                             break;
  230.                     }
  231.                 }
  232.             }
  233.         }
  234.         else
  235.         {
  236.             if(TransferPerfWindow)
  237.             {
  238.                 struct RastPort *RPort = TransferPerfWindow -> RPort;
  239.  
  240.                 if(MsgClass == IDCMP_NEWSIZE)
  241.                 {
  242.                     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  243.  
  244.                     RectFill(RPort,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  245.  
  246.                     CPL_Min = CPL_Avg = CPL_Cur = -1;
  247.                 }
  248.  
  249.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  250.                 {
  251.                     PutWindowInfo(WINDOW_PERF,TransferPerfWindow -> LeftEdge,TransferPerfWindow -> TopEdge,TransferPerfWindow -> Width,TransferPerfWindow -> Height);
  252.  
  253.                     CloseWindowSafely(TransferPerfWindow);
  254.  
  255.                     TransferPerfWindow = NULL;
  256.                 }
  257.             }
  258.         }
  259.     }
  260.  
  261.     return(Result);
  262. }
  263.  
  264.     /* NewFileName(STRPTR Source,STRPTR Buffer):
  265.      *
  266.      *    Build a valid file and path name, including path
  267.      *    substitution, etc.
  268.      */
  269.  
  270. STATIC STRPTR __regargs
  271. NewFileName(STRPTR Source,STRPTR Buffer)
  272. {
  273.     if(Config -> TransferConfig -> OverridePath && !Uploading)
  274.     {
  275.         if(DownloadPath)
  276.             strcpy(Buffer,DownloadPath);
  277.         else
  278.             strcpy(Buffer,Config -> PathConfig -> BinaryDownloadPath);
  279.  
  280.         if(!Buffer[0])
  281.         {
  282.             if(!GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  283.                 Buffer[0] = 0;
  284.         }
  285.  
  286.         if(Buffer[0])
  287.         {
  288.             if(AddPart(Buffer,FilePart(Source),MAX_FILENAME_LENGTH))
  289.                 return(Buffer);
  290.         }
  291.     }
  292.     else
  293.     {
  294.         if(FilePart(Source) == Source)
  295.         {
  296.             if(GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  297.             {
  298.                 if(AddPart(Buffer,Source,MAX_FILENAME_LENGTH))
  299.                     return(Buffer);
  300.             }
  301.         }
  302.     }
  303.  
  304.     strcpy(Buffer,Source);
  305.  
  306.     return(Source);
  307. }
  308.  
  309.     /* IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate):
  310.      *
  311.      *    Attach source information (BBS name, date and time) to a file.
  312.      */
  313.  
  314. STATIC VOID __regargs
  315. IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate)
  316. {
  317.     UBYTE            LocalBuffer[MAX_FILENAME_LENGTH],
  318.                     Time[40],
  319.                     Date[40];
  320.     struct DateTime    DateTime;
  321.  
  322.     CopyMem(OpenDate,&DateTime . dat_Stamp,sizeof(struct DateStamp));
  323.  
  324.         /* Prepare for date conversion. */
  325.  
  326.     DateTime . dat_Format    = FORMAT_DOS;
  327.     DateTime . dat_Flags    = 0;
  328.     DateTime . dat_StrDay    = NULL;
  329.     DateTime . dat_StrDate    = Date;
  330.     DateTime . dat_StrTime    = Time;
  331.  
  332.         /* Convert the date. */
  333.  
  334.     if(DateToStr(&DateTime))
  335.     {
  336.         StripSpaces(BBSName);
  337.         StripSpaces(Date);
  338.         StripSpaces(Time);
  339.  
  340.         if(BBSName[0])
  341.             SPrintf(LocalBuffer,"%s %s %s",BBSName,Date,Time);
  342.         else
  343.             SPrintf(LocalBuffer,"%s %s",Date,Time);
  344.  
  345.         SetComment(Name,LocalBuffer);
  346.     }
  347. }
  348.  
  349.     /* GetSeconds(STRPTR String):
  350.      *
  351.      *    Tries to turn a string of the format hh:mm:ss into
  352.      *    an integer number.
  353.      */
  354.  
  355. STATIC LONG __regargs
  356. GetSeconds(STRPTR String)
  357. {
  358.     UBYTE    Buffer[20];
  359.     LONG    Seconds = 0;
  360.  
  361.     memset(Buffer,0,20);
  362.  
  363.     strcpy(Buffer,String);
  364.  
  365.     Seconds += Atol(&Buffer[6]);
  366.  
  367.     Buffer[5] = 0;
  368.  
  369.     Seconds += Atol(&Buffer[3]) * 60;
  370.  
  371.     Buffer[2] = 0;
  372.  
  373.     Seconds += Atol(&Buffer[0]) * 3600;
  374.  
  375.     return(Seconds);
  376. }
  377.  
  378.     /* TruncateName(STRPTR FileName):
  379.      *
  380.      *    Truncates a file name to a maximum of 48 characters.
  381.      */
  382.  
  383. STATIC STRPTR __regargs
  384. TruncateName(STRPTR FileName)
  385. {
  386.     WORD Len = strlen(FileName);
  387.  
  388.     if(Len > 48)
  389.     {
  390.         WORD i;
  391.  
  392.         for(i = Len - 48 ; i < Len ; i++)
  393.         {
  394.             if(i >= Len - 44 && FileName[i] == '/')
  395.             {
  396.                 STATIC UBYTE __far NameBuffer[MAX_FILENAME_LENGTH];
  397.  
  398.                 strcpy(NameBuffer,".../");
  399.  
  400.                 strcat(NameBuffer,&FileName[i + 1]);
  401.  
  402.                 return(NameBuffer);
  403.             }
  404.         }
  405.     }
  406.  
  407.     return(FileName);
  408. }
  409.  
  410.     /* IsBlockMappedDevice(struct MsgPort *Handler):
  411.      *
  412.      *    See if the lock given points to a block mapped filing
  413.      *    system.
  414.      */
  415.  
  416. STATIC BOOL __regargs
  417. IsBlockMappedDevice(struct MsgPort *Handler)
  418. {
  419.     struct DosList    *Entry;
  420.     BOOL             IsBlockMapped = FALSE;
  421.  
  422.         // Find the device the lock belongs to
  423.  
  424.     if(Entry = LockDosList(LDF_DEVICES | LDF_READ))
  425.     {
  426.         while(Entry = NextDosEntry(Entry,LDF_DEVICES))
  427.         {
  428.             if(Entry -> dol_Task == Handler)
  429.             {
  430.                 struct FileSysStartupMsg *Startup = (struct FileSysStartupMsg *)BADDR(Entry -> dol_misc . dol_handler . dol_Startup);
  431.  
  432.                     // Plain filing system usually don't
  433.                     // use the startup entry
  434.  
  435.                 if(TypeOfMem(Startup))
  436.                 {
  437.                     STRPTR             Name        = (STRPTR)BADDR(Startup -> fssm_Device);
  438.                     struct DosEnvec    *Environ    = (struct DosEnvec *)BADDR(Startup -> fssm_Environ);
  439.  
  440.                         // Valid data in the startup entry?
  441.  
  442.                     if(TypeOfMem(Name) && TypeOfMem(Environ))
  443.                     {
  444.                         struct IOStdReq __aligned Request;
  445.  
  446.                         memset(&Request,0,sizeof(struct IOStdReq));
  447.  
  448.                             // Last chance, try to open the device driver
  449.  
  450.                         if(!OpenDevice(Name + 1,Startup -> fssm_Unit,&Request,Startup -> fssm_Flags))
  451.                         {
  452.                                 // This is a block mapped filing system
  453.  
  454.                             IsBlockMapped = TRUE;
  455.  
  456.                             CloseDevice(&Request);
  457.  
  458.                             break;
  459.                         }
  460.                     }
  461.                 }
  462.             }
  463.         }
  464.  
  465.         UnLockDosList(LDF_DEVICES | LDF_READ);
  466.     }
  467.  
  468.     return(IsBlockMapped);
  469. }
  470.  
  471.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  472.      *
  473.      *    Calculate the number of blocks a file will
  474.      *    occupy if saved to a disk.
  475.      */
  476.  
  477. STATIC LONG __regargs
  478. CalculateBlocks(LONG Size,LONG BlockSize)
  479. {
  480.     LONG    Blocks            = 1;        /* One for the file header. */
  481.     BYTE    HasExtension    = FALSE,    /* No extension block yet. */
  482.             Extension        = 0;        /* How many block pointers yet. */
  483.  
  484.         /* Round to next block. */
  485.  
  486.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  487.  
  488.     while(Size)
  489.     {
  490.             /* Add another block. */
  491.  
  492.         Blocks++;
  493.  
  494.             /* Subtract another block. */
  495.  
  496.         Size -= BlockSize;
  497.  
  498.             /* Add another block pointer, if 72 have been
  499.              * added, add another extension block.
  500.              */
  501.  
  502.         if((Extension++) == 72)
  503.         {
  504.                 /* If no extension block has been generated
  505.                  * yet, we were running on the block pointers
  506.                  * of the file header itself.
  507.                  */
  508.  
  509.             if(!HasExtension)
  510.                 HasExtension = TRUE;
  511.             else
  512.                 Blocks++;
  513.  
  514.                 /* Reset extension block counter. */
  515.  
  516.             Extension = 0;
  517.         }
  518.     }
  519.  
  520.     return(Blocks);
  521. }
  522.  
  523.     /* GetOptionMode(struct xpr_option *Option):
  524.      *
  525.      *    Turn text into a boolean value.
  526.      */
  527.  
  528. STATIC BYTE __regargs
  529. GetOptionMode(struct xpr_option *Option)
  530. {
  531.     if(Option)
  532.     {
  533.         STATIC STRPTR TrueOptions[] =
  534.         {
  535.             "ON",
  536.             "TRUE",
  537.             "T",
  538.             "YES",
  539.             "Y",
  540.             NULL
  541.         };
  542.  
  543.         register WORD i;
  544.  
  545.         for(i = 0 ; TrueOptions[i] ; i++)
  546.         {
  547.             if(!Stricmp(Option -> xpro_value,TrueOptions[i]))
  548.                 return(TRUE);
  549.         }
  550.     }
  551.  
  552.     return(FALSE);
  553. }
  554.  
  555.     /* SerialErrorReport(LONG Error):
  556.      *
  557.      *    Report a certain I/O error cause.
  558.      */
  559.  
  560. STATIC BYTE __regargs
  561. SerialErrorReport(LONG Error)
  562. {
  563.     STRPTR    ErrorMessage;
  564.     BYTE    IsFatal;
  565.  
  566.     switch(Error)
  567.     {
  568.         case SerErr_LineErr:
  569.  
  570.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_HARDWARE_DATA_OVERRUN_TXT);
  571.  
  572.             IsFatal = FALSE;
  573.  
  574.             break;
  575.  
  576.         case SerErr_ParityErr:
  577.  
  578.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_PARITY_ERROR_TXT);
  579.  
  580.             IsFatal = TRUE;
  581.  
  582.             break;
  583.  
  584.         case SerErr_TimerErr:
  585.  
  586.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_TIMER_ERROR_TXT);
  587.  
  588.             IsFatal = FALSE;
  589.  
  590.             break;
  591.  
  592.         case SerErr_BufOverflow:
  593.  
  594.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_READ_BUFFER_OVERFLOWED_TXT);
  595.  
  596.             IsFatal = FALSE;
  597.  
  598.             break;
  599.  
  600.         case SerErr_NoDSR:
  601.  
  602.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_NO_DSR_TXT);
  603.  
  604.             IsFatal = TRUE;
  605.  
  606.             break;
  607.  
  608.         case SerErr_DetectedBreak:
  609.  
  610.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_BREAK_DETECTED_TXT);
  611.  
  612.             IsFatal = TRUE;
  613.  
  614.             break;
  615.  
  616.         default:
  617.  
  618.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_UNKNOWN_CAUSE_TXT);
  619.  
  620.             IsFatal = FALSE;
  621.  
  622.             break;
  623.     }
  624.  
  625.     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_ERROR_TEMPLATE_TXT),Error,ErrorMessage);
  626.  
  627.     if(IsFatal)
  628.     {
  629.         TransferError = TRUE;
  630.  
  631.         return(TRUE);
  632.     }
  633.     else
  634.         return(FALSE);
  635. }
  636.  
  637.     /* xpr_fopen(STRPTR FileName,STRPTR AccessMode):
  638.      *
  639.      *    Open a file for random access.
  640.      */
  641.  
  642. LONG __saveds __asm
  643. xpr_fopen(register __a0 STRPTR FileName,register __a1 STRPTR AccessMode)
  644. {
  645.     UBYTE             RealName[MAX_FILENAME_LENGTH];
  646.     struct Buffer    *File;
  647.  
  648.     DB(kprintf("xpr_fopen(\"%s\",\"%s\")\n",FileName,AccessMode));
  649.  
  650.     Alerted = CarrierMessage = ErrorNotified = DontWorry = TypeChecked = FALSE;
  651.  
  652.         /* Reset transfer counters. */
  653.  
  654.     ByteVal = ByteMax = TimeVal = TimeMax = LastTimeDif = 0;
  655.  
  656.     LastPercent = -1;
  657.  
  658.         /* Reset CPS statistics. */
  659.  
  660.     CPS_Minimum    = (ULONG)~0;
  661.     CPS_Maximum    = 0;
  662.     CPS_Average    = 0;
  663.     CPS_Current    = 0;
  664.     CPS_Count    = 0;
  665.     CPS_Last    = 0;
  666.  
  667.         /* No window available for output? */
  668.  
  669.     if(!TransferWindow)
  670.         OpenTransferWindow();
  671.  
  672.     if(OriginalName[0])
  673.     {
  674.         if(!Stricmp(ShrunkenName,FileName))
  675.             FileName = OriginalName;
  676.     }
  677.  
  678.         /* Determine the file name. */
  679.  
  680.     FileName = NewFileName(FileName,RealName);
  681.  
  682.         /* Determine file transfer mode... */
  683.  
  684.     if(File = BufferOpen(FileName,AccessMode))
  685.     {
  686.         switch(AccessMode[0])
  687.         {
  688.             case 'r':
  689.  
  690.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  691.                 break;
  692.  
  693.             case 'w':
  694.  
  695.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  696.                 break;
  697.  
  698.             case 'a':
  699.  
  700.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  701.                 break;
  702.         }
  703.  
  704.         CurrentFile = File;
  705.     }
  706.  
  707.     DidTransfer = TRUE;
  708.  
  709.     return((LONG)File);
  710. }
  711.  
  712.     /* xpr_fclose(struct Buffer *File):
  713.      *
  714.      *    Close a file opened by xpr_fopen.
  715.      */
  716.  
  717. LONG __saveds __asm
  718. xpr_fclose(register __a0 struct Buffer *File)
  719. {
  720.     UBYTE                RealName[MAX_FILENAME_LENGTH];
  721.     struct DateStamp    OpenDate;
  722.     BYTE                WriteAccess,
  723.                         Used;
  724.  
  725.     DB(kprintf("xpr_fclose(0x%08lx)\n",File));
  726.  
  727.         /* This happened only once so far, but... */
  728.  
  729.     if(!File)
  730.     {
  731.         CurrentFile = NULL;
  732.  
  733.         return(1);
  734.     }
  735.  
  736.         /* Save some information. */
  737.  
  738.     OpenDate    = File -> OpenDate;
  739.     WriteAccess    = File -> WriteAccess;
  740.     Used        = File -> Used;
  741.  
  742.         /* Get the name of the file. */
  743.  
  744.     if(!NameFromFH(File -> FileHandle,RealName,MAX_FILENAME_LENGTH))
  745.         RealName[0] = 0;
  746.  
  747.         /* Close the file and see what it brings... */
  748.  
  749.     if(BufferClose(File) && RealName[0])
  750.     {
  751.             /* Did any access take place at all?
  752.              * xprzmodem.library for example just
  753.              * opens and closes a file in order to
  754.              * see if it exists.
  755.              */
  756.  
  757.         if(!Used)
  758.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  759.         else
  760.         {
  761.                 /* Did we receive or send a file? */
  762.  
  763.             if(WriteAccess)
  764.             {
  765.                 LONG Size;
  766.  
  767.                     /* Did the file remain empty? */
  768.  
  769.                 if(!(Size = GetFileSize(RealName)))
  770.                 {
  771.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  772.  
  773.                         /* Delete empty file. */
  774.  
  775.                     if(DeleteFile(RealName))
  776.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  777.                     else
  778.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  779.                 }
  780.                 else
  781.                 {
  782.                     struct Node *SomeNode;
  783.  
  784.                     if(ByteMax)
  785.                     {
  786.                         if(Size >= ByteMax)
  787.                             AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  788.                         else
  789.                             AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  790.                     }
  791.  
  792.                         /* Try to identify the file type. */
  793.  
  794.                     switch(Config -> TransferConfig -> IdentifyFiles)
  795.                     {
  796.                         case IDENTIFY_IGNORE:
  797.  
  798.                             if(Config -> MiscConfig -> CreateIcons)
  799.                                 Identify(RealName,FALSE);
  800.  
  801.                             break;
  802.  
  803.                         case IDENTIFY_FILETYPE:
  804.  
  805.                             Identify(RealName,TRUE);
  806.                             break;
  807.  
  808.                         case IDENTIFY_SOURCE:
  809.  
  810.                             IdentifySource(RealName,CurrentBBSName,&OpenDate);
  811.  
  812.                             if(Config -> MiscConfig -> CreateIcons)
  813.                                 Identify(RealName,FALSE);
  814.  
  815.                             break;
  816.                     }
  817.  
  818.                     if(CPS_Minimum == (ULONG)~0)
  819.                         CPS_Minimum = 0;
  820.  
  821.                     if(CPS_Count == 0)
  822.                     {
  823.                         CPS_Average    = 0;
  824.                         CPS_Count    = 1;
  825.                     }
  826.  
  827.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size,CPS_Minimum,CPS_Average / CPS_Count,CPS_Maximum);
  828.  
  829.                     if(SomeNode = CreateGenericListNode(0,RealName))
  830.                         AddGenericListNode(GenericListTable[GLIST_DOWNLOAD],SomeNode,ADD_GLIST_BOTTOM);
  831.                 }
  832.             }
  833.             else
  834.             {
  835.                     /* Set the archived bit on files we uploaded? */
  836.  
  837.                 if(Config -> TransferConfig -> SetArchivedBit)
  838.                 {
  839.                     struct FileInfoBlock *FileInfo;
  840.  
  841.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  842.                     {
  843.                         BPTR FileLock;
  844.  
  845.                             /* Get a lock on it. */
  846.  
  847.                         if(FileLock = Lock(RealName,ACCESS_READ))
  848.                         {
  849.                                 /* Examine the file. */
  850.  
  851.                             if(Examine(FileLock,FileInfo))
  852.                             {
  853.                                     /* Remove the lock. */
  854.  
  855.                                 UnLock(FileLock);
  856.  
  857.                                     /* Set the `archived' bit. */
  858.  
  859.                                 SetProtection(RealName,FileInfo -> fib_Protection | FIBF_ARCHIVE);
  860.                             }
  861.                             else
  862.                                 UnLock(FileLock);
  863.                         }
  864.  
  865.                         FreeDosObject(DOS_FIB,FileInfo);
  866.                     }
  867.                 }
  868.  
  869.                 AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  870.  
  871.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  872.  
  873.                 RemoveUploadListItem(RealName);
  874.             }
  875.         }
  876.     }
  877.  
  878.     CurrentFile = NULL;
  879.  
  880.     return(1);
  881. }
  882.  
  883.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  884.      *
  885.      *    Read a few bytes from a file.
  886.      */
  887.  
  888. LONG __saveds __asm
  889. xpr_fread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  890. {
  891.     DB(kprintf("xpr_fread(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File));
  892.  
  893.     return(BufferRead(File,Buffer,Size * Count) / Size);
  894. }
  895.  
  896.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  897.      *
  898.      *    Write a few bytes to a file.
  899.      */
  900.  
  901. LONG __saveds __asm
  902. xpr_fwrite(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  903. {
  904.     DB(kprintf("xpr_fwrite(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File));
  905.  
  906.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  907. }
  908.  
  909.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  910.      *
  911.      *    Move the read/write pointer in a file.
  912.      */
  913.  
  914. LONG __saveds __asm
  915. xpr_fseek(register __a0 struct Buffer *File,register __d0 LONG Offset,register __d1 LONG Origin)
  916. {
  917.     DB(kprintf("xpr_fseek(0x%08lx,%ld,%ld)\n",File,Offset,Origin));
  918.  
  919.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  920. }
  921.  
  922.     /* xpr_sread(APTR Buffer,LONG Size,LONG Timeout):
  923.      *
  924.      *    Read a few bytes from the serial port (including
  925.      *    timeouts).
  926.      */
  927.  
  928. #ifdef ASYNC_XPR_SREAD
  929.  
  930. #ifdef USE_THE_NEW_CODE
  931. LONG __saveds __asm
  932. xpr_sread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  933. {
  934.     DB(kprintf("xpr_sread(0x%08lx,%ld,%ld)\n",Buffer,Size,Timeout));
  935.  
  936.         /* No window available for output? */
  937.  
  938.     if(!TransferWindow)
  939.     {
  940.         if(!OpenTransferWindow())
  941.             return(-1);
  942.     }
  943.  
  944.         // IORequests available?
  945.  
  946.     if(ReadRequest && WriteRequest)
  947.     {
  948.             /* Valid size parameter? */
  949.  
  950.         if(Size > 0)
  951.         {
  952.             ULONG    Waiting;
  953.             UWORD    Status;
  954.  
  955.             GetSerialInfo(&Waiting,&Status);
  956.  
  957.             DB(kprintf("\033[0 p\033[1;1HStatus 0x%04lx Waiting %ld Size %ld Timeout %ld\033[K\n",Status,Waiting,Size,Timeout));
  958.  
  959.                 /* Return error if carrier is lost. */
  960.  
  961.             if((Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  962.             {
  963.                 if(!CarrierMessage)
  964.                 {
  965.                     CarrierMessage = TRUE;
  966.  
  967.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  968.                 }
  969.  
  970.                 ObtainSemaphore(&OnlineSemaphore);
  971.  
  972.                 if(Online)
  973.                 {
  974.                     WasOnline    = Online;
  975.                     Online        = FALSE;
  976.                 }
  977.  
  978.                 ReleaseSemaphore(&OnlineSemaphore);
  979.  
  980.                 TransferError = TRUE;
  981.  
  982.                 DB(kprintf("carrier lost.\n\033[J"));
  983.  
  984.                 return(-1);
  985.             }
  986.  
  987.                 // If no timeout is specified we should read as
  988.                 // many bytes as there are available. We can use
  989.                 // the same opportunity if there are already enough
  990.                 // bytes ready to satisfy the read request.
  991.  
  992.             if(!Timeout || Waiting >= Size)
  993.             {
  994.                 DB(kprintf("special case: timeout %ld waiting %ld size %ld\n\033[J",Timeout,Waiting,Size));
  995.  
  996.                 if(Waiting)
  997.                 {
  998.                     BYTE Error;
  999.  
  1000.                     if(Waiting > Size)
  1001.                         Waiting = Size;
  1002.  
  1003.                     if(Error = DoSerialRead(Buffer,Waiting))
  1004.                     {
  1005.                         DB(kprintf("\tread error %ld\n",Error));
  1006.  
  1007.                         if(SerialErrorReport(Error))
  1008.                             return(-1);
  1009.                         else
  1010.                             Waiting = ReadRequest -> IOSer . io_Actual;
  1011.                     }
  1012.  
  1013.                     DB(kprintf("read %ld bytes\n",Waiting));
  1014.  
  1015.                     BytesIn += Waiting;
  1016.                 }
  1017.  
  1018.                 return((LONG)Waiting);
  1019.             }
  1020.             else
  1021.             {
  1022.                     // We have to wait for enough data to arrive
  1023.  
  1024.                 register ULONG    SignalSet,
  1025.                                 SerialMask = PORTMASK(ReadPort),
  1026.                                 WindowMask = PORTMASK(TransferWindow -> UserPort);
  1027.  
  1028.                     /* Set up the timer. */
  1029.  
  1030.                 TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1031.                 TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  1032.                 TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  1033.  
  1034.                     /* Prevent early termination. */
  1035.  
  1036.                 ClrSignal(SIG_TIMER);
  1037.  
  1038.                     /* Set up the read request. */
  1039. #ifdef USE_QUICK_IO
  1040.                 if(StartSerialReadQuick(Buffer,Size))
  1041.                 {
  1042.                     BYTE Error;
  1043.  
  1044.                     DB(kprintf("very early termination\n"));
  1045.  
  1046.                         // If TRUE was returned, the read request
  1047.                         // did not get queued and was satisfied immediately.
  1048.  
  1049.                     if(Error = ReadRequest -> IOSer . io_Error)
  1050.                     {
  1051.                         if(SerialErrorReport(Error))
  1052.                             return(-1);
  1053.                     }
  1054.  
  1055.                     Size = ReadRequest -> IOSer . io_Actual;
  1056.  
  1057.                     BytesIn += Size;
  1058.  
  1059.                     DB(kprintf("%ld bytes read\n",Size));
  1060.  
  1061.                     return(Size);
  1062.                 }
  1063. #else
  1064.                 StartSerialRead(Buffer,Size);
  1065. #endif
  1066.                     // Start the timer
  1067.  
  1068.                 SendIO(TimeRequest);
  1069.  
  1070.                 DB(kprintf("waiting for input\n"));
  1071.  
  1072.                 FOREVER
  1073.                 {
  1074.                     SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  1075.  
  1076.                         /* Abort file transfer? */
  1077.  
  1078.                     if(SignalSet & WindowMask)
  1079.                     {
  1080.                         LONG Result = CheckAbort(FALSE);
  1081.  
  1082.                             /* Let's get out of here
  1083.                              * and hope that the protocol
  1084.                              * will call xpr_chkabort()
  1085.                              * in time.
  1086.                              */
  1087.  
  1088.                         if(Result != 0)
  1089.                         {
  1090.                             DB(kprintf("window report\n"));
  1091.  
  1092.                             if(TransferAbortState != Result)
  1093.                                 TransferAbortState = Result;
  1094.  
  1095.                                 /* Abort the read request. */
  1096.  
  1097.                             StopSerialRead();
  1098.  
  1099.                                 /* Remove the timer request. */
  1100.  
  1101.                             if(!CheckIO(TimeRequest))
  1102.                                 AbortIO(TimeRequest);
  1103.  
  1104.                             WaitIO(TimeRequest);
  1105.  
  1106.                                 /* Does the user want to cancel
  1107.                                  * the transmission?
  1108.                                  */
  1109.  
  1110.                             if(Result < 0)
  1111.                             {
  1112.                                     // Do it the hard way
  1113.  
  1114.                                 if(TransferAbortCount++)
  1115.                                 {
  1116.                                         // Oh Janet, don't tell me to can it
  1117.  
  1118.                                     if(UsesZModem)
  1119.                                         DoSerialWrite(ZModemCancel,20);
  1120.  
  1121.                                     return(Result);
  1122.                                 }
  1123.                             }
  1124.  
  1125.                                 /* Did the driver receive any
  1126.                                  * data?
  1127.                                  */
  1128.  
  1129.                             if(ReadRequest -> IOSer . io_Actual)
  1130.                             {
  1131.                                 BytesIn += ReadRequest -> IOSer . io_Actual;
  1132.  
  1133.                                 return((LONG)ReadRequest -> IOSer . io_Actual);
  1134.                             }
  1135.                             else
  1136.                             {
  1137.                                     /* Take a second look and query the number of
  1138.                                      * bytes ready to be received, there may
  1139.                                      * still be some bytes in the buffer.
  1140.                                      * Note: this depends on the way the
  1141.                                      * driver handles read abort.
  1142.                                      */
  1143.  
  1144.                                 Waiting = GetSerialWaiting();
  1145.  
  1146.                                     /* Don't read too much. */
  1147.  
  1148.                                 if(Waiting > Size)
  1149.                                     Waiting = Size;
  1150.  
  1151.                                     /* Are there any bytes to be transferred? */
  1152.  
  1153.                                 if(Waiting)
  1154.                                 {
  1155.                                     BYTE Error;
  1156.  
  1157.                                         /* Read the data. */
  1158.  
  1159.                                     if(Error = DoSerialRead(Buffer,Waiting))
  1160.                                     {
  1161.                                         if(SerialErrorReport(Error))
  1162.                                             return(-1);
  1163.                                         else
  1164.                                             Waiting = ReadRequest -> IOSer . io_Actual;
  1165.                                     }
  1166.  
  1167.                                     BytesIn += Waiting;
  1168.                                 }
  1169.  
  1170.                                 return((LONG)Waiting);
  1171.                             }
  1172.                         }
  1173.                     }
  1174.  
  1175.                         /* Receive buffer filled? */
  1176.  
  1177.                     if(SignalSet & SerialMask)
  1178.                     {
  1179.                         BYTE Error;
  1180.  
  1181.                         DB(kprintf("serial input\n"));
  1182.  
  1183.                             /* Abort the timer request. */
  1184.  
  1185.                         if(!CheckIO(TimeRequest))
  1186.                             AbortIO(TimeRequest);
  1187.  
  1188.                             /* Did the request terminate gracefully? */
  1189.  
  1190.                         if(Error = WaitSerialRead())
  1191.                         {
  1192.                             DB(kprintf("error %ld\n",Error));
  1193.  
  1194.                             if(SerialErrorReport(Error))
  1195.                                 return(-1);
  1196.                             else
  1197.                                 Size = ReadRequest -> IOSer . io_Actual;
  1198.                         }
  1199.  
  1200.                         DB(kprintf("%ld bytes read\n",Size));
  1201.  
  1202.                         BytesIn += Size;
  1203.  
  1204.                             /* Wait for the timer to stop ticking. */
  1205.  
  1206.                         WaitIO(TimeRequest);
  1207.  
  1208.                         return(Size);
  1209.                     }
  1210.  
  1211.                         /* Hit by timeout? */
  1212.  
  1213.                     if(SignalSet & SIG_TIMER)
  1214.                     {
  1215.                         DB(kprintf("timer event\n"));
  1216.  
  1217.                             /* Abort the read request. */
  1218.  
  1219.                         StopSerialRead();
  1220.  
  1221.                             /* Remove the timer request. */
  1222.  
  1223.                         WaitIO(TimeRequest);
  1224.  
  1225.                             /* Did the driver receive any
  1226.                              * data?
  1227.                              */
  1228.  
  1229.                         if(ReadRequest -> IOSer . io_Actual)
  1230.                         {
  1231.                             DB(kprintf("got %ld bytes\n",ReadRequest -> IOSer . io_Actual));
  1232.  
  1233.                             BytesIn += ReadRequest -> IOSer . io_Actual;
  1234.  
  1235.                             return((LONG)ReadRequest -> IOSer . io_Actual);
  1236.                         }
  1237.                         else
  1238.                         {
  1239.                                 /* Take a second look and query the number of
  1240.                                  * bytes ready to be received, there may
  1241.                                  * still be some bytes in the buffer.
  1242.                                  * Note: this depends on the way the
  1243.                                  * driver handles read abort.
  1244.                                  */
  1245.  
  1246.                             Waiting = GetSerialWaiting();
  1247.  
  1248.                             DB(kprintf("%ld bytes are waiting\n",Waiting));
  1249.  
  1250.                                 /* Don't read too much. */
  1251.  
  1252.                             if(Waiting > Size)
  1253.                                 Waiting = Size;
  1254.  
  1255.                                 /* Are there any bytes to be transferred? */
  1256.  
  1257.                             if(Waiting)
  1258.                             {
  1259.                                 BYTE Error;
  1260.  
  1261.                                 DB(kprintf("reading %ld bytes\n",Waiting));
  1262.  
  1263.                                     /* Read the data. */
  1264.  
  1265.                                 if(Error = DoSerialRead(Buffer,Waiting))
  1266.                                 {
  1267.                                     DB(kprintf("error %ld\n",Error));
  1268.  
  1269.                                     if(SerialErrorReport(Error))
  1270.                                         return(-1);
  1271.                                     else
  1272.                                         Waiting = ReadRequest -> IOSer . io_Actual;
  1273.                                 }
  1274.  
  1275.                                 BytesIn += Waiting;
  1276.                             }
  1277.  
  1278.                             DB(kprintf("read %ld bytes\n",Waiting));
  1279.  
  1280.                             return((LONG)Waiting);
  1281.                         }
  1282.                     }
  1283.                 }
  1284.             }
  1285.         }
  1286.         else
  1287.             return(0);
  1288.     }
  1289.     else
  1290.         return(-1);
  1291. }
  1292. #else
  1293. LONG __saveds __asm
  1294. xpr_sread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  1295. {
  1296. /*    kprintf("xpr_sread(0x%08lx,%ld,%ld)\n",Buffer,Size,Timeout);*/
  1297.  
  1298.         /* No window available for output? */
  1299.  
  1300.     if(!TransferWindow)
  1301.     {
  1302.         if(!OpenTransferWindow())
  1303.             return(-1);
  1304.     }
  1305.  
  1306.         /* Are both IORequests available? */
  1307.  
  1308.     if(WriteRequest && ReadRequest)
  1309.     {
  1310.             /* Valid size parameter? */
  1311.  
  1312.         if(Size > 0)
  1313.         {
  1314.             ULONG    Waiting;
  1315.             UWORD    Status;
  1316.  
  1317.             GetSerialInfo(&Waiting,&Status);
  1318.  
  1319.                 /* Return error if carrier is lost. */
  1320.  
  1321.             if(Config -> SerialConfig -> CheckCarrier)
  1322.             {
  1323.                 if(Status & CIAF_COMCD)
  1324.                 {
  1325.                     if(!CarrierMessage)
  1326.                     {
  1327.                         CarrierMessage = TRUE;
  1328.  
  1329.                         AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  1330.                     }
  1331.  
  1332.                     ObtainSemaphore(&OnlineSemaphore);
  1333.  
  1334.                     if(Online)
  1335.                     {
  1336.                         WasOnline    = Online;
  1337.                         Online        = FALSE;
  1338.                     }
  1339.  
  1340.                     ReleaseSemaphore(&OnlineSemaphore);
  1341.  
  1342.                     TransferError = TRUE;
  1343.  
  1344.                     return(-1);
  1345.                 }
  1346.             }
  1347.  
  1348.             if(Waiting)
  1349.             {
  1350.                     /* No timeout specified? Read as many
  1351.                      * bytes as available.
  1352.                      */
  1353.  
  1354.                 if(!Timeout)
  1355.                 {
  1356.                     if(Waiting > Size)
  1357.                         Waiting = Size;
  1358.  
  1359.                     if(DoSerialRead(Buffer,Waiting))
  1360.                     {
  1361.                         if(SerialErrorReport(ReadRequest -> IOSer . io_Error))
  1362.                             return(-1);
  1363.                         else
  1364.                             Waiting = ReadRequest -> IOSer . io_Actual;
  1365.                     }
  1366.  
  1367.                     BytesIn += Waiting;
  1368.  
  1369.                     return((LONG)Waiting);
  1370.                 }
  1371.  
  1372.                     /* Enough data pending to be read? */
  1373.  
  1374.                 if(Waiting >= Size)
  1375.                 {
  1376.                     if(DoSerialRead(Buffer,Size))
  1377.                     {
  1378.                         if(SerialErrorReport(ReadRequest -> IOSer . io_Error))
  1379.                             return(-1);
  1380.                         else
  1381.                             Size = ReadRequest -> IOSer . io_Actual;
  1382.                     }
  1383.  
  1384.                     BytesIn += Size;
  1385.  
  1386.                     return(Size);
  1387.                 }
  1388.             }
  1389.             else
  1390.             {
  1391.                     /* No timeout & no bytes available:
  1392.                      * return immediately.
  1393.                      */
  1394.  
  1395.                 if(!Timeout)
  1396.                     return(0);
  1397.             }
  1398.  
  1399.             /* ALWAYS */
  1400.             {
  1401.                 register ULONG    SignalSet,
  1402.                                 SerialMask = PORTMASK(ReadPort),
  1403.                                 WindowMask = PORTMASK(TransferWindow -> UserPort);
  1404.  
  1405.                     /* Set up the timer. */
  1406.  
  1407.                 TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1408.                 TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  1409.                 TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  1410.  
  1411.                     /* Prevent early termination. */
  1412.  
  1413.                 ClrSignal(SerialMask | SIG_TIMER);
  1414.  
  1415.                     /* Start IO... */
  1416.  
  1417.                 SendIO(TimeRequest);
  1418.  
  1419.                     /* Set up the read request. */
  1420.  
  1421.                 StartSerialRead(Buffer,Size);
  1422.  
  1423.                 FOREVER
  1424.                 {
  1425.                     SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  1426.  
  1427.                         /* Abort file transfer? */
  1428.  
  1429.                     if(SignalSet & WindowMask)
  1430.                     {
  1431.                         LONG Result = CheckAbort(FALSE);
  1432.  
  1433.                             /* Let's get out of here
  1434.                              * and hope that the protocol
  1435.                              * will call xpr_chkabort()
  1436.                              * in time.
  1437.                              */
  1438.  
  1439.                         if(Result)
  1440.                         {
  1441.                             if(TransferAbortState != Result)
  1442.                                 TransferAbortState = Result;
  1443.  
  1444.                                 /* Does the user want to cancel
  1445.                                  * the transmission?
  1446.                                  */
  1447.  
  1448.                             if(Result < 0)
  1449.                             {
  1450.                                     // Do it the hard way
  1451.  
  1452.                                 if(TransferAbortCount++)
  1453.                                 {
  1454.                                     StopSerialRead();
  1455.  
  1456.                                     if(!CheckIO(TimeRequest))
  1457.                                         AbortIO(TimeRequest);
  1458.  
  1459.                                     WaitIO(TimeRequest);
  1460.  
  1461.                                         // Oh Janet, don't tell me to can it
  1462.  
  1463.                                     if(UsesZModem)
  1464.                                         DoSerialWrite(ZModemCancel,20);
  1465.  
  1466.                                     return(Result);
  1467.                                 }
  1468.                             }
  1469.  
  1470.                                 /* Abort the read request. */
  1471.  
  1472.                             StopSerialRead();
  1473.  
  1474.                                 /* Remove the timer request. */
  1475.  
  1476.                             if(!CheckIO(TimeRequest))
  1477.                                 AbortIO(TimeRequest);
  1478.  
  1479.                             WaitIO(TimeRequest);
  1480.  
  1481.                                 /* Did the driver receive any
  1482.                                  * data?
  1483.                                  */
  1484.  
  1485.                             if(ReadRequest -> IOSer . io_Actual)
  1486.                             {
  1487.                                 BytesIn += ReadRequest -> IOSer . io_Actual;
  1488.  
  1489.                                 return((LONG)ReadRequest -> IOSer . io_Actual);
  1490.                             }
  1491.                             else
  1492.                             {
  1493.                                     /* Take a second look and query the number of
  1494.                                      * bytes ready to be received, there may
  1495.                                      * still be some bytes in the buffer.
  1496.                                      * Note: this depends on the way the
  1497.                                      * driver handles read abort.
  1498.                                      */
  1499.  
  1500.                                 Waiting = GetSerialWaiting();
  1501.  
  1502.                                     /* Don't read too much. */
  1503.  
  1504.                                 if(Size > Waiting)
  1505.                                     Size = Waiting;
  1506.  
  1507.                                     /* Are there any bytes to be transferred? */
  1508.  
  1509.                                 if(Size)
  1510.                                 {
  1511.                                         /* Read the data. */
  1512.  
  1513.                                     if(DoSerialRead(Buffer,Size))
  1514.                                     {
  1515.                                         if(SerialErrorReport(ReadRequest -> IOSer . io_Error))
  1516.                                             return(-1);
  1517.                                         else
  1518.                                             Size = ReadRequest -> IOSer . io_Actual;
  1519.                                     }
  1520.  
  1521.                                     BytesIn += Size;
  1522.                                 }
  1523.  
  1524.                                 return(Size);
  1525.                             }
  1526.                         }
  1527.                     }
  1528.  
  1529.                         /* Receive buffer filled? */
  1530.  
  1531.                     if(SignalSet & SerialMask)
  1532.                     {
  1533.                             /* Abort the timer request. */
  1534.  
  1535.                         if(!CheckIO(TimeRequest))
  1536.                             AbortIO(TimeRequest);
  1537.  
  1538.                         WaitIO(TimeRequest);
  1539.  
  1540.                             /* Did the request terminate gracefully? */
  1541.  
  1542.                         if(WaitSerialRead())
  1543.                         {
  1544.                             if(SerialErrorReport(ReadRequest -> IOSer . io_Error))
  1545.                                 return(-1);
  1546.                             else
  1547.                                 Size = ReadRequest -> IOSer . io_Actual;
  1548.                         }
  1549.  
  1550.                         BytesIn += Size;
  1551.  
  1552.                         return(Size);
  1553.                     }
  1554.  
  1555.                         /* Hit by timeout? */
  1556.  
  1557.                     if(SignalSet & SIG_TIMER)
  1558.                     {
  1559.                             /* Abort the read request. */
  1560.  
  1561.                         StopSerialRead();
  1562.  
  1563.                             /* Remove the timer request. */
  1564.  
  1565.                         WaitIO(TimeRequest);
  1566.  
  1567.                             /* Did the driver receive any
  1568.                              * data?
  1569.                              */
  1570.  
  1571.                         if(ReadRequest -> IOSer . io_Actual)
  1572.                         {
  1573.                             BytesIn += ReadRequest -> IOSer . io_Actual;
  1574.  
  1575.                             return((LONG)ReadRequest -> IOSer . io_Actual);
  1576.                         }
  1577.                         else
  1578.                         {
  1579.                                 /* Take a second look and query the number of
  1580.                                  * bytes ready to be received, there may
  1581.                                  * still be some bytes in the buffer.
  1582.                                  * Note: this depends on the way the
  1583.                                  * driver handles read abort.
  1584.                                  */
  1585.  
  1586.                             Waiting = GetSerialWaiting();
  1587.  
  1588.                                 /* Don't read too much. */
  1589.  
  1590.                             if(Size > Waiting)
  1591.                                 Size = Waiting;
  1592.  
  1593.                                 /* Are there any bytes to be transferred? */
  1594.  
  1595.                             if(Size)
  1596.                             {
  1597.                                     /* Read the data. */
  1598.  
  1599.                                 if(DoSerialRead(Buffer,Size))
  1600.                                 {
  1601.                                     if(SerialErrorReport(ReadRequest -> IOSer . io_Error))
  1602.                                         return(-1);
  1603.                                     else
  1604.                                         Size = ReadRequest -> IOSer . io_Actual;
  1605.                                 }
  1606.  
  1607.                                 BytesIn += Size;
  1608.                             }
  1609.  
  1610.                             return(Size);
  1611.                         }
  1612.                     }
  1613.                 }
  1614.             }
  1615.         }
  1616.         else
  1617.             return(0);
  1618.     }
  1619.     else
  1620.         return(-1);
  1621. }
  1622. #endif    // USE_THE_NEW_CODE
  1623.  
  1624. #else    // ASYNC_XPR_SREAD
  1625.  
  1626. LONG __saveds __asm
  1627. xpr_sread(register __a0 UBYTE *Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  1628. {
  1629.     DB(kprintf("xpr_sread(0x%08lx,%ld,%ld)\n",Buffer,Size,Timeout));
  1630.  
  1631.         /* No window available for output? */
  1632.  
  1633.     if(!TransferWindow)
  1634.     {
  1635.         if(!OpenTransferWindow())
  1636.             return(-1);
  1637.     }
  1638.  
  1639.         /* Valid size parameter? */
  1640.  
  1641.     if(Size > 0)
  1642.     {
  1643.         LONG Total = 0;
  1644.  
  1645.             /* Return error if carrier is lost. */
  1646.  
  1647.         if(Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  1648.         {
  1649.             if(GetSerialStatus() & CIAF_COMCD)
  1650.             {
  1651.                 if(!CarrierMessage)
  1652.                 {
  1653.                     CarrierMessage = TRUE;
  1654.  
  1655.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  1656.                 }
  1657.  
  1658.                 ObtainSemaphore(&OnlineSemaphore);
  1659.  
  1660.                 if(Online)
  1661.                 {
  1662.                     WasOnline    = Online;
  1663.                     Online        = FALSE;
  1664.                 }
  1665.  
  1666.                 ReleaseSemaphore(&OnlineSemaphore);
  1667.  
  1668.                 TransferError = TRUE;
  1669.  
  1670.                 return(-1);
  1671.             }
  1672.         }
  1673.  
  1674.             // Did the read request terminate, is data available?
  1675.  
  1676.         if(CheckSerialRead())
  1677.         {
  1678.             LONG Error;
  1679.  
  1680.                 // Pick it up...
  1681.  
  1682.             if(Error = WaitSerialRead())
  1683.             {
  1684.                 LONG Result;
  1685.  
  1686.                 if(SerialErrorReport(Error))
  1687.                     Result = -1;
  1688.                 else
  1689.                     Result = 0;
  1690.  
  1691.                 RestartSerial();
  1692.  
  1693.                 return(Result);
  1694.             }
  1695.  
  1696.                 // One byte was read
  1697.  
  1698.             *Buffer++ = ReadBuffer[0];
  1699.             Size--;
  1700.             BytesIn++;
  1701.             Total++;
  1702.  
  1703.                 // Is there still something to be read?
  1704.  
  1705.             if(Size > 0)
  1706.             {
  1707.                 ULONG    Waiting;
  1708.                 LONG    Result;
  1709.  
  1710.                     // Check how many bytes are still
  1711.                     // waiting to be read
  1712.  
  1713.                 if(Waiting = GetSerialWaiting())
  1714.                 {
  1715.                     LONG Error;
  1716.  
  1717.                         // Don't read too many
  1718.  
  1719.                     if(Waiting > Size)
  1720.                         Waiting = Size;
  1721.  
  1722.                     if(Error = DoSerialRead(Buffer,Waiting))
  1723.                     {
  1724.                         if(SerialErrorReport(Error))
  1725.                             Result = -1;
  1726.                         else
  1727.                             Result = 0;
  1728.                     }
  1729.                     else
  1730.                         Result = Waiting;
  1731.                 }
  1732.                 else
  1733.                     Result = 0;
  1734.  
  1735.                     // Did we get an error?
  1736.  
  1737.                 if(Result > 0)
  1738.                 {
  1739.                     Buffer    += Result;
  1740.                     Size    -= Result;
  1741.                     BytesIn    += Result;
  1742.                     Total    += Result;
  1743.  
  1744.                     Result++;
  1745.                 }
  1746.  
  1747.                 RestartSerial();
  1748.  
  1749.                     // Now check if there is a timeout value
  1750.                     // given. If there is, we need to fill the
  1751.                     // buffer with as many bytes as there are
  1752.                     // requested and may not be able to return
  1753.                     // right now. We will return if enough
  1754.                     // data was read or if an error occured.
  1755.  
  1756.                 if(!Timeout || Result < 0 || !Size)
  1757.                     return(Result);
  1758.             }
  1759.             else
  1760.             {
  1761.                 RestartSerial();
  1762.  
  1763.                 return(1);
  1764.             }
  1765.         }
  1766.         else
  1767.         {
  1768.                 // No data is available and no timeout
  1769.                 // is given. We can't deliver anything,
  1770.                 // so let's scram.
  1771.  
  1772.             if(!Timeout)
  1773.                 return(0);
  1774.         }
  1775.  
  1776.             // At this point we still need to read some data
  1777.             // and a timeout is given.
  1778.  
  1779.         /* ALWAYS */
  1780.         {
  1781.             register ULONG    SerialMask = PORTMASK(ReadPort),
  1782.                             WindowMask = PORTMASK(TransferWindow -> UserPort),
  1783.                             SignalSet;
  1784.  
  1785.                 /* Set up the timer. */
  1786.  
  1787.             TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1788.             TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  1789.             TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  1790.  
  1791.                 /* Prevent early termination. */
  1792.  
  1793.             ClrSignal(SIG_TIMER);
  1794.  
  1795.                 /* Start IO... */
  1796.  
  1797.             SendIO(TimeRequest);
  1798.  
  1799.             FOREVER
  1800.             {
  1801.                 SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  1802.  
  1803.                     /* Abort file transfer? */
  1804.  
  1805.                 if(SignalSet & WindowMask)
  1806.                 {
  1807.                     LONG Result = CheckAbort(FALSE);
  1808.  
  1809.                         /* Let's get out of here
  1810.                          * and hope that the protocol
  1811.                          * will call xpr_chkabort()
  1812.                          * in time.
  1813.                          */
  1814.  
  1815.                     if(Result)
  1816.                     {
  1817.                             /* Abort the timer request. */
  1818.  
  1819.                         if(!CheckIO(TimeRequest))
  1820.                             AbortIO(TimeRequest);
  1821.  
  1822.                         WaitIO(TimeRequest);
  1823.  
  1824.                         if(TransferAbortState != Result)
  1825.                             TransferAbortState = Result;
  1826.  
  1827.                             /* Does the user want to cancel
  1828.                              * the transmission?
  1829.                              */
  1830.  
  1831.                         if(Result < 0)
  1832.                         {
  1833.                                 // Do it the hard way
  1834.  
  1835.                             if(TransferAbortCount++)
  1836.                             {
  1837.                                     // Oh Janet, don't tell me to can it
  1838.  
  1839.                                 DoSerialWrite(ZModemCancel,20);
  1840.  
  1841.                                 FlushSerialRead();
  1842.                             }
  1843.                         }
  1844.  
  1845.                         return(Result);
  1846.                     }
  1847.                 }
  1848.  
  1849.                     /* Receive buffer filled? */
  1850.  
  1851.                 if(SignalSet & SerialMask)
  1852.                 {
  1853.                     LONG Error;
  1854.  
  1855.                         /* Did the request terminate gracefully? */
  1856.  
  1857.                     if(Error = WaitSerialRead())
  1858.                     {
  1859.                             // Start collecting data again
  1860.  
  1861.                         RestartSerial();
  1862.  
  1863.                             // Is it a fatal error?
  1864.  
  1865.                         if(SerialErrorReport(Error))
  1866.                         {
  1867.                                 /* Abort the timer request. */
  1868.  
  1869.                             if(!CheckIO(TimeRequest))
  1870.                                 AbortIO(TimeRequest);
  1871.  
  1872.                             WaitIO(TimeRequest);
  1873.  
  1874.                             return(-1);
  1875.                         }
  1876.                     }
  1877.                     else
  1878.                     {
  1879.                             // One byte was read
  1880.  
  1881.                         *Buffer++ = ReadBuffer[0];
  1882.                         Size--;
  1883.                         BytesIn++;
  1884.                         Total++;
  1885.  
  1886.                             // Is there still something to be read?
  1887.  
  1888.                         if(Size > 0)
  1889.                         {
  1890.                             ULONG    Waiting;
  1891.                             LONG    Result;
  1892.  
  1893.                                 // Check how many bytes are still
  1894.                                 // waiting to be read
  1895.  
  1896.                             if(Waiting = GetSerialWaiting())
  1897.                             {
  1898.                                 LONG Error;
  1899.  
  1900.                                     // Don't read too many
  1901.  
  1902.                                 if(Waiting > Size)
  1903.                                     Waiting = Size;
  1904.  
  1905.                                 if(Error = DoSerialRead(Buffer,Waiting))
  1906.                                 {
  1907.                                     if(SerialErrorReport(Error))
  1908.                                         Result = -1;
  1909.                                     else
  1910.                                         Result = 0;
  1911.                                 }
  1912.                                 else
  1913.                                     Result = Waiting;
  1914.                             }
  1915.                             else
  1916.                                 Result = 0;
  1917.  
  1918.                                 // Did we get an error?
  1919.  
  1920.                             if(Result < 0)
  1921.                             {
  1922.                                     /* Abort the timer request. */
  1923.  
  1924.                                 if(!CheckIO(TimeRequest))
  1925.                                     AbortIO(TimeRequest);
  1926.  
  1927.                                 WaitIO(TimeRequest);
  1928.  
  1929.                                 RestartSerial();
  1930.  
  1931.                                 return(-1);
  1932.                             }
  1933.                             else
  1934.                             {
  1935.                                 Buffer    += Result;
  1936.                                 Size    -= Result;
  1937.                                 BytesIn    += Result;
  1938.                                 Total    += Result;
  1939.                             }
  1940.                         }
  1941.  
  1942.                         RestartSerial();
  1943.  
  1944.                         if(!Size)
  1945.                         {
  1946.                                 /* Abort the timer request. */
  1947.  
  1948.                             if(!CheckIO(TimeRequest))
  1949.                                 AbortIO(TimeRequest);
  1950.  
  1951.                             WaitIO(TimeRequest);
  1952.  
  1953.                             return(Total);
  1954.                         }
  1955.                     }
  1956.                 }
  1957.  
  1958.                     /* Hit by timeout? */
  1959.  
  1960.                 if(SignalSet & SIG_TIMER)
  1961.                 {
  1962.                         /* Remove the timer request. */
  1963.  
  1964.                     WaitIO(TimeRequest);
  1965.  
  1966.                         /* Did the driver receive any
  1967.                          * data?
  1968.                          */
  1969.  
  1970.                     if(CheckSerialRead())
  1971.                     {
  1972.                         LONG Error;
  1973.  
  1974.                             /* Did the request terminate gracefully? */
  1975.  
  1976.                         if(Error = WaitSerialRead())
  1977.                         {
  1978.                                 // Start collecting data again
  1979.  
  1980.                             RestartSerial();
  1981.  
  1982.                                 // Is it a fatal error?
  1983.  
  1984.                             if(SerialErrorReport(Error))
  1985.                                 return(-1);
  1986.                         }
  1987.                         else
  1988.                         {
  1989.                                 // One byte was read
  1990.  
  1991.                             *Buffer++ = ReadBuffer[0];
  1992.                             Size--;
  1993.                             BytesIn++;
  1994.                             Total++;
  1995.  
  1996.                                 // Is there still something to be read?
  1997.  
  1998.                             if(Size > 0)
  1999.                             {
  2000.                                 ULONG    Waiting;
  2001.                                 LONG    Result;
  2002.  
  2003.                                     // Check how many bytes are still
  2004.                                     // waiting to be read
  2005.  
  2006.                                 if(Waiting = GetSerialWaiting())
  2007.                                 {
  2008.                                     LONG Error;
  2009.  
  2010.                                         // Don't read too many
  2011.  
  2012.                                     if(Waiting > Size)
  2013.                                         Waiting = Size;
  2014.  
  2015.                                     if(Error = DoSerialRead(Buffer,Waiting))
  2016.                                     {
  2017.                                         if(SerialErrorReport(Error))
  2018.                                             Result = -1;
  2019.                                         else
  2020.                                             Result = 0;
  2021.                                     }
  2022.                                     else
  2023.                                         Result = Waiting;
  2024.                                 }
  2025.                                 else
  2026.                                     Result = 0;
  2027.  
  2028.                                     // Did we get an error?
  2029.  
  2030.                                 if(Result < 0)
  2031.                                 {
  2032.                                     RestartSerial();
  2033.  
  2034.                                     return(-1);
  2035.                                 }
  2036.                                 else
  2037.                                 {
  2038.                                     Size    -= Result;
  2039.                                     BytesIn    += Result;
  2040.                                     Total    += Result;
  2041.                                 }
  2042.                             }
  2043.  
  2044.                             RestartSerial();
  2045.                         }
  2046.                     }
  2047.  
  2048.                     return(Total);
  2049.                 }
  2050.             }
  2051.         }
  2052.     }
  2053.     else
  2054.         return(0);
  2055. }
  2056. #endif    // ASYNC_XPR_SREAD
  2057.  
  2058.     /* xpr_swrite(APTR Buffer,LONG Size):
  2059.      *
  2060.      *    Write a few bytes to the serial port.
  2061.      */
  2062.  
  2063. LONG __saveds __asm
  2064. xpr_swrite(register __a0 APTR Buffer,register __d0 LONG Size)
  2065. {
  2066.     LONG Error;
  2067.  
  2068.     DB(kprintf("xpr_swrite(0x%08lx,%ld)\n",Buffer,Size));
  2069.  
  2070.         /* Return error if carrier is lost. */
  2071.  
  2072.     if(Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  2073.     {
  2074.             /* Is the carrier signal still present? */
  2075.  
  2076.         if(GetSerialStatus() & CIAF_COMCD)
  2077.         {
  2078.             if(!CarrierMessage)
  2079.             {
  2080.                 CarrierMessage = TRUE;
  2081.  
  2082.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  2083.             }
  2084.  
  2085.             ObtainSemaphore(&OnlineSemaphore);
  2086.  
  2087.             if(Online)
  2088.             {
  2089.                 WasOnline    = Online;
  2090.                 Online        = FALSE;
  2091.             }
  2092.  
  2093.             ReleaseSemaphore(&OnlineSemaphore);
  2094.  
  2095.             TransferError = TRUE;
  2096.  
  2097.             return(-1);
  2098.         }
  2099.     }
  2100.  
  2101.         /* Send the data. */
  2102.  
  2103.     if(Error = DoSerialWrite(Buffer,Size))
  2104.     {
  2105.         if(SerialErrorReport(Error))
  2106.             return(-1);
  2107.     }
  2108.     else
  2109.         BytesOut += Size;
  2110.  
  2111.     return(0);
  2112. }
  2113.  
  2114.     /* xpr_sflush():
  2115.      *
  2116.      *    Release the contents of all serial buffers.
  2117.      */
  2118.  
  2119. LONG __saveds __asm
  2120. xpr_sflush()
  2121. {
  2122.     DB(kprintf("xpr_sflush()\n"));
  2123.  
  2124.     return((LONG)FlushSerialRead());
  2125. }
  2126.  
  2127.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  2128.      *
  2129.      *    Update the information displayed in the transfer window.
  2130.      */
  2131.  
  2132. LONG __saveds __asm
  2133. xpr_update(register __a0 struct XPR_UPDATE *UpdateInfo)
  2134. {
  2135.     DB(kprintf("xpr_update(0x%08lx)\n",UpdateInfo));
  2136.  
  2137.         /* No window available for output? */
  2138.  
  2139.     if(!TransferWindow)
  2140.     {
  2141.         if(!OpenTransferWindow())
  2142.             return(0);
  2143.     }
  2144.  
  2145.     if(UpdateInfo)
  2146.     {
  2147.         BYTE    NewByte = FALSE,
  2148.                 NewTime = FALSE;
  2149.  
  2150.         if(TransferWindow -> Flags & WFLG_ZOOMED)
  2151.         {
  2152.             BOOLEAN Refresh;
  2153.  
  2154.             if(!TransferZoomed)
  2155.             {
  2156.                 ULONG Micros;
  2157.  
  2158.                 CurrentTime(&LastSeconds,&Micros);
  2159.  
  2160.                 Refresh = TRUE;
  2161.  
  2162.                 TransferZoomed = TRUE;
  2163.             }
  2164.             else
  2165.             {
  2166.                 ULONG Seconds,Micros;
  2167.  
  2168.                 CurrentTime(&Seconds,&Micros);
  2169.  
  2170.                 if(Seconds > LastSeconds)
  2171.                 {
  2172.                     LastSeconds = Seconds;
  2173.  
  2174.                     Refresh = TRUE;
  2175.                 }
  2176.             }
  2177.  
  2178.             if(Refresh)
  2179.             {
  2180.                 if(LastPercent > 0)
  2181.                     SPrintf(TransferTitleBuffer,"%s [%s %ld%%]",TransferWindowTitle,TruncateName(RealName),LastPercent);
  2182.                 else
  2183.                     SPrintf(TransferTitleBuffer,"%s [%s]",TransferWindowTitle,TruncateName(RealName));
  2184.  
  2185.                 SetWindowTitles(TransferWindow,TransferTitleBuffer,(STRPTR)-1);
  2186.             }
  2187.         }
  2188.         else
  2189.         {
  2190.             if(TransferZoomed)
  2191.             {
  2192.                 SetWindowTitles(TransferWindow,TransferWindowTitle,(STRPTR)-1);
  2193.  
  2194.                 TransferZoomed = FALSE;
  2195.             }
  2196.         }
  2197.  
  2198.         if((UpdateInfo -> xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo -> xpru_protocol)
  2199.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_PROTOCOL,GTTX_Text,UpdateInfo -> xpru_protocol,TAG_DONE);
  2200.  
  2201.         if((UpdateInfo -> xpru_updatemask & XPRU_MSG) && UpdateInfo -> xpru_msg)
  2202.             AddTransferInfo(FALSE,UpdateInfo -> xpru_msg);
  2203.  
  2204.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo -> xpru_errormsg)
  2205.             AddTransferInfo(TRUE,UpdateInfo -> xpru_errormsg);
  2206.  
  2207.         if((UpdateInfo -> xpru_updatemask & XPRU_FILENAME) && UpdateInfo -> xpru_filename)
  2208.         {
  2209.             STRPTR FileName = UpdateInfo -> xpru_filename;
  2210.  
  2211.             if(OriginalName[0])
  2212.             {
  2213.                 if(!Stricmp(ShrunkenName,FileName))
  2214.                     FileName = OriginalName;
  2215.             }
  2216.  
  2217.             FileName = NewFileName(FileName,RealName);
  2218.  
  2219.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,0,LABX_Text,TruncateName(FileName),TAG_DONE);
  2220.  
  2221.             if(FileTransferInfo)
  2222.             {
  2223.                 if(FileTransferInfo -> CurrentFile)
  2224.                 {
  2225.                     struct FileTransferNode *Node = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  2226.  
  2227.                     if(Node -> Node . mln_Succ)
  2228.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,TruncateName(Node -> Name),TAG_DONE);
  2229.                     else
  2230.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,LocaleString(MSG_GLOBAL_NONE_TXT),TAG_DONE);
  2231.                 }
  2232.  
  2233.                 PrintBox(GAD_TRANSFER_SIZE,2,ConvNumber,FileTransferInfo -> TotalSize);
  2234.  
  2235.                 if(FileTransferInfo -> TotalFiles)
  2236.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,(100 * FileTransferInfo -> DoneFiles) / FileTransferInfo -> TotalFiles);
  2237.                 else
  2238.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,0);
  2239.             }
  2240.         }
  2241.  
  2242.         if((UpdateInfo -> xpru_updatemask & XPRU_FILESIZE) && UpdateInfo -> xpru_filesize != -1)
  2243.         {
  2244.             if(CurrentFile)
  2245.             {
  2246.                 if(CurrentFile -> InfoPort)
  2247.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber10,UpdateInfo -> xpru_filesize);
  2248.                 else
  2249.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  2250.             }
  2251.             else
  2252.                 PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  2253.  
  2254.             if(ByteMax = UpdateInfo -> xpru_filesize)
  2255.                 NewByte = TRUE;
  2256.         }
  2257.  
  2258.         if((UpdateInfo -> xpru_updatemask & XPRU_BYTES) && UpdateInfo -> xpru_bytes != -1)
  2259.         {
  2260.             if(CurrentFile)
  2261.             {
  2262.                 if(CurrentFile -> InfoPort)
  2263.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber10,ByteVal = UpdateInfo -> xpru_bytes);
  2264.                 else
  2265.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  2266.             }
  2267.             else
  2268.                 PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  2269.  
  2270.             if(FileTransferInfo)
  2271.             {
  2272.                 ULONG Len = FileTransferInfo -> DoneSize + UpdateInfo -> xpru_bytes;
  2273.  
  2274.                 if(FileTransferInfo -> TotalSize)
  2275.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,(100 * Len) / FileTransferInfo -> TotalSize);
  2276.                 else
  2277.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,0);
  2278.             }
  2279.  
  2280.             if(ByteMax)
  2281.                 NewByte = TRUE;
  2282.  
  2283.             if(CurrentFile)
  2284.             {
  2285.                 if(CurrentFile -> InfoPort && !Uploading)
  2286.                 {
  2287.                     if(CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  2288.                     {
  2289.                         if(ByteMax)
  2290.                         {
  2291.                             register LONG Space = CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed;
  2292.  
  2293.                             if(Space >= 0)
  2294.                             {
  2295.                                     // Important! Only use the number of bytes still
  2296.                                     // to be transferred.
  2297.  
  2298.                                 register LONG Blocks = CalculateBlocks(ByteMax - ByteVal,CurrentFile -> InfoData . id_BytesPerBlock);
  2299.  
  2300.                                     // Did we take a look at the filing system yet?
  2301.  
  2302.                                 if(!TypeChecked)
  2303.                                 {
  2304.                                         // If this is not a block mapped device
  2305.                                         // we cannot guess what will happen if
  2306.                                         // it fills up (and whether it fills up at all).
  2307.  
  2308.                                     if(!IsBlockMappedDevice(CurrentFile -> InfoPort))
  2309.                                         DontWorry = TRUE;
  2310.  
  2311.                                         // Ok, done
  2312.  
  2313.                                     TypeChecked = TRUE;
  2314.                                 }
  2315.  
  2316.                                 if(Space >= Blocks || DontWorry)
  2317.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,"");
  2318.                                 else
  2319.                                 {
  2320.                                     if(!Alerted)
  2321.                                     {
  2322.                                         Alerted = TRUE;
  2323.  
  2324.                                         Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  2325.                                     }
  2326.  
  2327.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,LocaleString(MSG_TERMXPR_FILE_MAY_NOT_FIT_TXT));
  2328.                                 }
  2329.                             }
  2330.                             else
  2331.                                 PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  2332.                         }
  2333.                         else
  2334.                             PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  2335.                     }
  2336.                 }
  2337.             }
  2338.         }
  2339.  
  2340.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKS) && UpdateInfo -> xpru_blocks != -1)
  2341.             PrintBox(GAD_TRANSFER_SIZE,5,ConvNumber,UpdateInfo -> xpru_blocks);
  2342.  
  2343.         if((UpdateInfo -> xpru_updatemask & XPRU_DATARATE) && UpdateInfo -> xpru_datarate > 0)
  2344.         {
  2345.             register LONG Change;
  2346.  
  2347.             CPS_Current = UpdateInfo -> xpru_datarate;
  2348.  
  2349.             if(CPS_Last)
  2350.             {
  2351.                 if(CPS_Last < UpdateInfo -> xpru_datarate)
  2352.                     Change = (100 * (UpdateInfo -> xpru_datarate - CPS_Last)) / CPS_Last;
  2353.                 else
  2354.                     Change = (100 * (CPS_Last - UpdateInfo -> xpru_datarate)) / CPS_Last;
  2355.             }
  2356.             else
  2357.                 Change = 100;
  2358.  
  2359.             if(Change > 1)
  2360.             {
  2361.                 PrintBox(GAD_TRANSFER_SECONDS,0,ConvNumber,UpdateInfo -> xpru_datarate);
  2362.  
  2363.                 CPS_Last = UpdateInfo -> xpru_datarate;
  2364.             }
  2365.  
  2366.             if(UpdateInfo -> xpru_datarate < CPS_Minimum)
  2367.                 CPS_Minimum = UpdateInfo -> xpru_datarate;
  2368.  
  2369.             if(UpdateInfo -> xpru_datarate > CPS_Maximum)
  2370.                 CPS_Maximum = UpdateInfo -> xpru_datarate;
  2371.  
  2372.             if((ULONG)(CPS_Average + UpdateInfo -> xpru_datarate) >= CPS_Average)
  2373.             {
  2374.                 CPS_Average += UpdateInfo -> xpru_datarate;
  2375.  
  2376.                 CPS_Count++;
  2377.             }
  2378.         }
  2379.  
  2380.         if((UpdateInfo -> xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo -> xpru_chardelay != -1)
  2381.             PrintBox(GAD_TRANSFER_SECONDS,1,ConvNumber,UpdateInfo -> xpru_chardelay);
  2382.  
  2383.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo -> xpru_packetdelay != -1)
  2384.             PrintBox(GAD_TRANSFER_SECONDS,2,ConvNumber,UpdateInfo -> xpru_packetdelay);
  2385.  
  2386.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo -> xpru_packettype != -1)
  2387.         {
  2388.             if(UpdateInfo -> xpru_packettype > 32 && UpdateInfo -> xpru_packettype < 256)
  2389.             {
  2390.                 if(IsPrintable[UpdateInfo -> xpru_packettype])
  2391.                     PrintBox(GAD_TRANSFER_SECONDS,3,"`%lc'",UpdateInfo -> xpru_packettype);
  2392.                 else
  2393.                     PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  2394.             }
  2395.             else
  2396.                 PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  2397.         }
  2398.  
  2399.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo -> xpru_blockcheck)
  2400.             PrintBox(GAD_TRANSFER_SECONDS,4,UpdateInfo -> xpru_blockcheck);
  2401.  
  2402.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo -> xpru_blocksize != -1)
  2403.             PrintBox(GAD_TRANSFER_SECONDS,5,ConvNumber,UpdateInfo -> xpru_blocksize);
  2404.  
  2405.  
  2406.         if((UpdateInfo -> xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo -> xpru_expecttime)
  2407.         {
  2408.             PrintBox(GAD_TRANSFER_TOTALTIME,0,UpdateInfo -> xpru_expecttime);
  2409.  
  2410.             if(TimeMax = GetSeconds((STRPTR)UpdateInfo -> xpru_expecttime))
  2411.                 NewTime = TRUE;
  2412.         }
  2413.  
  2414.         if((UpdateInfo -> xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo -> xpru_elapsedtime)
  2415.         {
  2416.             PrintBox(GAD_TRANSFER_TOTALTIME,1,UpdateInfo -> xpru_elapsedtime);
  2417.  
  2418.             TimeVal = GetSeconds((STRPTR)UpdateInfo -> xpru_elapsedtime);
  2419.  
  2420.             if(TimeMax)
  2421.                 NewTime = TRUE;
  2422.         }
  2423.  
  2424.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORS) && UpdateInfo -> xpru_errors != -1)
  2425.         {
  2426.             PrintBox(GAD_TRANSFER_ERRORS,0,ConvNumber,UpdateInfo -> xpru_errors);
  2427.  
  2428.             if(!ErrorNotified && Config -> TransferConfig -> ErrorNotification && UpdateInfo -> xpru_errors >= Config -> TransferConfig -> ErrorNotification)
  2429.             {
  2430.                 ErrorNotified = TRUE;
  2431.  
  2432.                 WakeUp(TransferWindow,SOUND_ERROR);
  2433.             }
  2434.         }
  2435.  
  2436.         if((UpdateInfo -> xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo -> xpru_timeouts != -1)
  2437.             PrintBox(GAD_TRANSFER_ERRORS,1,ConvNumber,UpdateInfo -> xpru_timeouts);
  2438.  
  2439.         if(NewByte)
  2440.         {
  2441.             LONG Percent;
  2442.  
  2443.             if(ByteMax)
  2444.                 Percent = (100 * ByteVal) / ByteMax;
  2445.             else
  2446.                 Percent = 0;
  2447.  
  2448.             if(Percent != LastPercent)
  2449.             {
  2450.                 UBYTE LocalBuffer[10];
  2451.  
  2452.                 SPrintf(LocalBuffer,"%ld%%",Percent);
  2453.  
  2454.                 LastPercent = Percent;
  2455.  
  2456.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_PERCENT,
  2457.                     LAGA_Percent,    Percent,
  2458.                     LAGA_InfoText,    LocalBuffer,
  2459.                 TAG_DONE);
  2460.             }
  2461.         }
  2462.  
  2463.         if(NewTime)
  2464.         {
  2465.             register LONG TimeDif,Change;
  2466.  
  2467.             if(TimeVal > TimeMax)
  2468.                 TimeDif = 0;
  2469.             else
  2470.                 TimeDif = TimeMax - TimeVal;
  2471.  
  2472.             if(LastTimeDif)
  2473.             {
  2474.                 if(LastTimeDif < TimeDif)
  2475.                     Change = (100 * (TimeDif - LastTimeDif)) / LastTimeDif;
  2476.                 else
  2477.                     Change = (100 * (LastTimeDif - TimeDif)) / LastTimeDif;
  2478.             }
  2479.             else
  2480.                 Change = 100;
  2481.  
  2482.                 /* Don't update the display unless the change
  2483.                  * exceeds 2% of the previous value.
  2484.                  */
  2485.  
  2486.             if(Change > 2)
  2487.             {
  2488.                 UBYTE    LocalBuffer[10];
  2489.                 LONG    Percent;
  2490.  
  2491.                 LastTimeDif = TimeDif;
  2492.  
  2493.                 if(TimeMax)
  2494.                     Percent = (100 * TimeDif) / TimeMax;
  2495.                 else
  2496.                     Percent = 0;
  2497.  
  2498.                 SPrintf(LocalBuffer,"%2ld:%02ld:%02ld",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60);
  2499.  
  2500.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_TIME,
  2501.                     LAGA_Percent,    Percent,
  2502.                     LAGA_InfoText,    LocalBuffer,
  2503.                 TAG_DONE);
  2504.  
  2505.                     /* A rapidly changing transfer time display would
  2506.                      * cause the transfer completion time display to
  2507.                      * change at the same pace. As the completion time
  2508.                      * display calculation is rather costly, a change smaller
  2509.                      * than 5% of the previous value is silently ignored.
  2510.                      */
  2511.  
  2512.                 if(Change > 5)
  2513.                 {
  2514.                     UBYTE            DateTimeBuffer[256];
  2515.                     struct DateStamp    Stamp;
  2516.  
  2517.                         /* Obtain current time. */
  2518.  
  2519.                     DateStamp(&Stamp);
  2520.  
  2521.                         /* Add the time to go. */
  2522.  
  2523.                     Stamp . ds_Tick        += (TimeDif % 60) * TICKS_PER_SECOND;
  2524.                     Stamp . ds_Minute    += TimeDif / 60 + Stamp . ds_Tick / (60 * TICKS_PER_SECOND);
  2525.                     Stamp . ds_Days        += Stamp . ds_Minute / 1440;
  2526.  
  2527.                     Stamp . ds_Tick        %= 60 * TICKS_PER_SECOND;
  2528.                     Stamp . ds_Minute    %= 1440;
  2529.  
  2530.                         /* Conversion succeeded? */
  2531.  
  2532.                     if(FormatStamp(&Stamp,NULL,NULL,DateTimeBuffer,TRUE))
  2533.                         PrintBox(GAD_TRANSFER_FILE,3,DateTimeBuffer);
  2534.                 }
  2535.             }
  2536.         }
  2537.     }
  2538.  
  2539.     if(TransferPerfWindow)
  2540.     {
  2541.         struct RastPort *RPort = TransferPerfWindow -> RPort;
  2542.         LONG Height,Left,Top,Min,Avg,Cur;
  2543.  
  2544.         Left    = TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1);
  2545.         Height    = TransferPerfWindow -> Height - (TransferPerfWindow -> BorderTop + TransferPerfWindow -> BorderBottom + 1);
  2546.         Top        = TransferPerfWindow -> BorderTop + Height;
  2547.  
  2548.         if(CPS_Maximum && CPS_Maximum != ~0)
  2549.         {
  2550.             Min = (Height * CPS_Minimum) / CPS_Maximum;
  2551.             Cur = (Height * CPS_Current) / CPS_Maximum;
  2552.  
  2553.             if(CPS_Count)
  2554.                 Avg = ((CPS_Average / CPS_Count) * Height) / CPS_Maximum;
  2555.             else
  2556.                 Avg = 0;
  2557.         }
  2558.         else
  2559.             Min = Avg = Cur = 0;
  2560.  
  2561.         if(CPL_Min == -1)
  2562.             CPL_Min = Min;
  2563.  
  2564.         if(CPL_Avg == -1)
  2565.             CPL_Avg = Avg;
  2566.  
  2567.         if(CPL_Cur == -1)
  2568.             CPL_Cur = Cur;
  2569.  
  2570.         ScrollRaster(RPort,1,0,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  2571.  
  2572.         if(CPL_Cur != -1 && Cur != -1)
  2573.         {
  2574.             SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
  2575.             Move(RPort,Left,Top - CPL_Cur);
  2576.             Draw(RPort,Left,Top - Cur);
  2577.         }
  2578.  
  2579.         if(CPL_Min != -1 && Min != -1)
  2580.         {
  2581.             SetAPen(RPort,DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN]);
  2582.             Move(RPort,Left,Top - CPL_Min);
  2583.             Draw(RPort,Left,Top - Min);
  2584.         }
  2585.  
  2586.         if(CPL_Avg != -1 && Avg != -1)
  2587.         {
  2588.             SetAPen(RPort,DrawInfo -> dri_Pens[FILLPEN]);
  2589.             Move(RPort,Left,Top - CPL_Avg);
  2590.             Draw(RPort,Left,Top - Avg);
  2591.         }
  2592.  
  2593.         CPL_Min = Min;
  2594.         CPL_Avg = Avg;
  2595.         CPL_Cur = Cur;
  2596.     }
  2597.  
  2598.     return(1);
  2599. }
  2600.  
  2601.     /* xpr_chkabort():
  2602.      *
  2603.      *    Check if the user has aborted the transfer.
  2604.      */
  2605.  
  2606. LONG __saveds __asm
  2607. xpr_chkabort()
  2608. {
  2609.     LONG Result;
  2610.  
  2611.     DB(kprintf("xpr_chkabort()\n"));
  2612.  
  2613.     if(TransferAbortState != 0)
  2614.     {
  2615.         Result = TransferAbortState;
  2616.  
  2617.         TransferAbortState = 0;
  2618.     }
  2619.     else
  2620.         Result = CheckAbort(Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection);
  2621.  
  2622.     return(Result);
  2623. }
  2624.  
  2625.     /* xpr_gets(STRPTR Prompt,STRPTR Buffer):
  2626.      *
  2627.      *    Prompt the user for string input.
  2628.      */
  2629.  
  2630. LONG __saveds __asm
  2631. xpr_gets(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  2632. {
  2633.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  2634.  
  2635.     struct LayoutHandle    *Handle;
  2636.     LONG                 Success = FALSE;
  2637.     UBYTE                 LocalBuffer[256];
  2638.  
  2639.     DB(kprintf("xpr_gets(\"%s\",\"%s\")\n",Prompt,Buffer));
  2640.  
  2641.     if(strlen(Buffer) > 255)
  2642.     {
  2643.         CopyMem(Buffer,LocalBuffer,255);
  2644.  
  2645.         LocalBuffer[255] = 0;
  2646.     }
  2647.     else
  2648.         strcpy(LocalBuffer,Buffer);
  2649.  
  2650.     if(!Prompt)
  2651.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  2652.  
  2653.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  2654.         LH_LocaleHook,    &LocaleHook,
  2655.     TAG_DONE))
  2656.     {
  2657.         struct Window *PanelWindow;
  2658.  
  2659.         LT_New(Handle,
  2660.             LA_Type,    VERTICAL_KIND,
  2661.         TAG_DONE);
  2662.         {
  2663.             LT_New(Handle,
  2664.                 LA_Type,    VERTICAL_KIND,
  2665.                 LA_LabelText,    Prompt,
  2666.             TAG_DONE);
  2667.             {
  2668.                 LT_New(Handle,
  2669.                     LA_Type,    STRING_KIND,
  2670.                     LA_STRPTR,    LocalBuffer,
  2671.                     LA_ID,        GAD_STRING,
  2672.                     LA_Chars,    30,
  2673.                 TAG_DONE);
  2674.  
  2675.                 LT_EndGroup(Handle);
  2676.             }
  2677.  
  2678.             LT_New(Handle,
  2679.                 LA_Type,VERTICAL_KIND,
  2680.             TAG_DONE);
  2681.             {
  2682.                 LT_New(Handle,
  2683.                     LA_Type,        XBAR_KIND,
  2684.                     LAXB_FullSize,    TRUE,
  2685.                 TAG_DONE);
  2686.  
  2687.                 LT_EndGroup(Handle);
  2688.             }
  2689.  
  2690.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  2691.                 LAGR_SameSize,    TRUE,
  2692.                 LAGR_Spread,    TRUE,
  2693.             TAG_DONE);
  2694.             {
  2695.                 LT_New(Handle,
  2696.                     LA_Type,        BUTTON_KIND,
  2697.                     LA_LabelID,        MSG_TERMXPR_OKAY_GAD,
  2698.                     LA_ID,            GAD_OK,
  2699.                     LABT_ReturnKey,    TRUE,
  2700.                     LABT_ExtraFat,    TRUE,
  2701.                 TAG_DONE);
  2702.  
  2703.                 LT_New(Handle,
  2704.                     LA_Type,        BUTTON_KIND,
  2705.                     LA_LabelID,        MSG_GLOBAL_CANCEL_GAD,
  2706.                     LA_ID,            GAD_CANCEL,
  2707.                     LABT_EscKey,    TRUE,
  2708.                     LABT_ExtraFat,    TRUE,
  2709.                 TAG_DONE);
  2710.  
  2711.                 LT_EndGroup(Handle);
  2712.             }
  2713.         }
  2714.  
  2715.         if(PanelWindow = LT_Build(Handle,
  2716.             LAWN_TitleID,        MSG_GLOBAL_ENTER_TEXT_TXT,
  2717.             LAWN_IDCMP,            IDCMP_CLOSEWINDOW,
  2718.             LAWN_HelpHook,        &GuideHook,
  2719.             LAWN_Parent,        Window,
  2720.             WA_DepthGadget,        TRUE,
  2721.             WA_CloseGadget,        TRUE,
  2722.             WA_DragBar,            TRUE,
  2723.             WA_RMBTrap,            TRUE,
  2724.             WA_Activate,        TRUE,
  2725.             WA_SimpleRefresh,    TRUE,
  2726.         TAG_DONE))
  2727.         {
  2728.             struct IntuiMessage    *Message;
  2729.             BOOLEAN                 Done = FALSE;
  2730.             ULONG                 MsgClass;
  2731.             UWORD                 MsgCode;
  2732.             struct Gadget        *MsgGadget;
  2733.  
  2734.             PushWindow(PanelWindow);
  2735.  
  2736.             LT_ShowWindow(Handle,TRUE);
  2737.  
  2738.             LT_Activate(Handle,GAD_STRING);
  2739.  
  2740.             do
  2741.             {
  2742.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  2743.                     break;
  2744.  
  2745.                 while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
  2746.                 {
  2747.                     MsgClass        = Message -> Class;
  2748.                     MsgCode            = Message -> Code;
  2749.                     MsgGadget        = (struct Gadget *)Message -> IAddress;
  2750.  
  2751.                     LT_ReplyIMsg(Message);
  2752.  
  2753.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  2754.                         Done = TRUE;
  2755.  
  2756.                     if(MsgClass == IDCMP_GADGETUP)
  2757.                     {
  2758.                         switch(MsgGadget -> GadgetID)
  2759.                         {
  2760.                             case GAD_STRING:
  2761.  
  2762.                                 if(MsgCode == '\r')
  2763.                                 {
  2764.                                     if(strcmp(Buffer,LocalBuffer))
  2765.                                         NewOptions = TRUE;
  2766.  
  2767.                                     strcpy(Buffer,LocalBuffer);
  2768.  
  2769.                                     Success = Done = TRUE;
  2770.  
  2771.                                     LT_PressButton(Handle,GAD_OK);
  2772.                                 }
  2773.  
  2774.                                 break;
  2775.  
  2776.                             case GAD_OK:
  2777.  
  2778.                                 LT_UpdateStrings(Handle);
  2779.  
  2780.                                 if(strcmp(Buffer,LocalBuffer))
  2781.                                     NewOptions = TRUE;
  2782.  
  2783.                                 strcpy(Buffer,LocalBuffer);
  2784.  
  2785.                                 Success = Done = TRUE;
  2786.  
  2787.                                 break;
  2788.  
  2789.                             case GAD_CANCEL:
  2790.  
  2791.                                 Done = TRUE;
  2792.                                 break;
  2793.                         }
  2794.                     }
  2795.                 }
  2796.             }
  2797.             while(!Done);
  2798.  
  2799.             PopWindow();
  2800.         }
  2801.  
  2802.         LT_DeleteHandle(Handle);
  2803.     }
  2804.  
  2805.     return(Success);
  2806. }
  2807.  
  2808.     /* xpr_setserial(LONG Status):
  2809.      *
  2810.      *    Set/read the serial status (parameters).
  2811.      */
  2812.  
  2813. LONG __saveds __asm
  2814. xpr_setserial(register __d0 LONG Status)
  2815. {
  2816.     DB(kprintf("xpr_setserial(0x%08lx)\n",Status));
  2817.  
  2818.     if(WriteRequest)
  2819.     {
  2820.         STATIC LONG XprBauds[12] =
  2821.         {
  2822.                110,
  2823.                300,
  2824.               1200,
  2825.               2400,
  2826.               4800,
  2827.               9600,
  2828.              19200,
  2829.              31250,
  2830.              38400,
  2831.              57600,
  2832.              76800,
  2833.             115200
  2834.         };
  2835.  
  2836.         LONG Return,i;
  2837.  
  2838.         StopSerialRead();
  2839.         StopSerialWrite();
  2840.  
  2841.         DoSerialCmd(SDCMD_QUERY);
  2842.  
  2843.         Return = WriteRequest -> io_SerFlags & 0xFF;
  2844.  
  2845.         if(WriteRequest -> io_ExtFlags & SEXTF_MSPON)
  2846.             Return |= ST_PARTYMARKON;
  2847.  
  2848.         if(WriteRequest -> io_ExtFlags & SEXTF_MARK)
  2849.             Return |= ST_PARTYMARK;
  2850.  
  2851.         if(WriteRequest -> io_StopBits == 2)
  2852.             Return |= ST_2BITS;
  2853.  
  2854.         if(WriteRequest -> io_ReadLen == 7)
  2855.             Return |= ST_READ7;
  2856.  
  2857.         if(WriteRequest -> io_WriteLen == 7)
  2858.             Return |= ST_WRITE7;
  2859.  
  2860.         for(i = 0 ; i < 12 ; i++)
  2861.         {
  2862.             if(XprBauds[i] >= WriteRequest -> io_Baud)
  2863.             {
  2864.                 Return |= (i << 16);
  2865.  
  2866.                 break;
  2867.             }
  2868.         }
  2869.  
  2870.             /* Update serial parameters, don't change
  2871.              * the baud rate however.
  2872.              */
  2873.  
  2874.         if(Status != -1)
  2875.         {
  2876.             WriteRequest -> io_SerFlags = Status & 0xFF;
  2877.             WriteRequest -> io_ExtFlags = 0;
  2878.  
  2879.             if(Status & ST_PARTYMARKON)
  2880.                 WriteRequest -> io_ExtFlags |= SEXTF_MSPON;
  2881.  
  2882.             if(Status & ST_PARTYMARK)
  2883.                 WriteRequest -> io_ExtFlags |= SEXTF_MARK;
  2884.  
  2885.             if(Status & ST_2BITS)
  2886.                 WriteRequest -> io_StopBits = 2;
  2887.             else
  2888.                 WriteRequest -> io_StopBits = 1;
  2889.  
  2890.             if(Status & ST_READ7)
  2891.                 WriteRequest -> io_ReadLen = 7;
  2892.             else
  2893.                 WriteRequest -> io_ReadLen = 8;
  2894.  
  2895.             if(Status & ST_WRITE7)
  2896.                 WriteRequest -> io_WriteLen = 7;
  2897.             else
  2898.                 WriteRequest -> io_WriteLen = 8;
  2899.  
  2900.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  2901.  
  2902.             DoIO(WriteRequest);
  2903.  
  2904.             CopyMem(WriteRequest,ReadRequest,sizeof(struct IOExtSer));
  2905.  
  2906.             ReadRequest -> IOSer . io_Message . mn_ReplyPort = ReadPort;
  2907.  
  2908.             CopyWriteFlags();
  2909.  
  2910.             if(WriteRequest -> io_SerFlags & SERF_7WIRE)
  2911.             {
  2912.                 if(Config -> SerialConfig -> HandshakingProtocol == HANDSHAKING_NONE)
  2913.                     Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_RTSCTS_DSR;
  2914.             }
  2915.             else
  2916.             {
  2917.                 if(Config -> SerialConfig -> HandshakingProtocol != HANDSHAKING_NONE)
  2918.                     Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_NONE;
  2919.             }
  2920.         }
  2921.  
  2922.         RestartSerial();
  2923.  
  2924.         return(Return);
  2925.     }
  2926.     else
  2927.         return(-1);
  2928. }
  2929.  
  2930.     /* xpr_ffirst(STRPTR Buffer,STRPTR Pattern):
  2931.      *
  2932.      *    Batch file upload: find the first matching file and return
  2933.      *    its name.
  2934.      */
  2935.  
  2936. LONG __saveds __asm
  2937. xpr_ffirst(register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  2938. {
  2939.     DB(kprintf("xpr_ffirst(0x%08lx,\"%s\")\n",Buffer,Pattern));
  2940.  
  2941.     if(FileTransferInfo)
  2942.     {
  2943.         FileTransferInfo -> DoneSize    = 0;
  2944.         FileTransferInfo -> DoneFiles    = 0;
  2945.  
  2946.         FileTransferInfo -> CurrentFile    = (struct FileTransferNode *)FileTransferInfo -> FileList . mlh_Head;
  2947.         FileTransferInfo -> CurrentSize    = FileTransferInfo -> CurrentFile -> Size;
  2948.  
  2949.         if(Config -> TransferConfig -> MangleFileNames)
  2950.         {
  2951.             UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  2952.  
  2953.             strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  2954.  
  2955.             ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  2956.  
  2957.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2958.  
  2959.             Char = PathPart(Buffer);
  2960.  
  2961.             *Char = 0;
  2962.  
  2963.             AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2964.  
  2965.             strcpy(ShrunkenName,Buffer);
  2966.         }
  2967.         else
  2968.         {
  2969.             OriginalName[0] = 0;
  2970.  
  2971.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2972.         }
  2973.  
  2974.         return(1);
  2975.     }
  2976.     else
  2977.         return(0);
  2978. }
  2979.  
  2980.     /* xpr_fnext(LONG OldState,STRPTR Buffer,STRPTR Pattern):
  2981.      *
  2982.      *    Batch file upload: find the next matching file
  2983.      *    - if any - and return its name.
  2984.      */
  2985.  
  2986. LONG __saveds __asm
  2987. xpr_fnext(register __d0 LONG OldState,register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  2988. {
  2989.     DB(kprintf("xpr_fnext(%ld,0x%08lx,\"%s\")\n",OldState,Buffer,Pattern));
  2990.  
  2991.     if(FileTransferInfo)
  2992.     {
  2993.         if(FileTransferInfo -> CurrentFile -> Node . mln_Succ -> mln_Succ)
  2994.         {
  2995.             FileTransferInfo -> DoneSize    += FileTransferInfo -> CurrentSize;
  2996.             FileTransferInfo -> DoneFiles    += 1;
  2997.  
  2998.             FileTransferInfo -> CurrentFile  = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  2999.             FileTransferInfo -> CurrentSize  = FileTransferInfo -> CurrentFile -> Size;
  3000.  
  3001.             if(Config -> TransferConfig -> MangleFileNames)
  3002.             {
  3003.                 UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  3004.  
  3005.                 strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  3006.  
  3007.                 ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  3008.  
  3009.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  3010.  
  3011.                 Char = PathPart(Buffer);
  3012.  
  3013.                 *Char = 0;
  3014.  
  3015.                 AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  3016.  
  3017.                 strcpy(ShrunkenName,Buffer);
  3018.             }
  3019.             else
  3020.             {
  3021.                 OriginalName[0] = 0;
  3022.  
  3023.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  3024.             }
  3025.  
  3026.             return(1);
  3027.         }
  3028.     }
  3029.  
  3030.     return(0);
  3031. }
  3032.  
  3033.     /* xpr_finfo(STRPTR FileName,LONG InfoType):
  3034.      *
  3035.      *    Return information on a given file.
  3036.      */
  3037.  
  3038. LONG __saveds __asm
  3039. xpr_finfo(register __a0 STRPTR FileName,register __d0 LONG InfoType)
  3040. {
  3041.     struct FileInfoBlock    *FileInfo;
  3042.     LONG                     Size;
  3043.  
  3044.     DB(kprintf("xpr_finfo(\"%s\",%ld)\n",FileName,InfoType));
  3045.  
  3046.     switch(InfoType)
  3047.     {
  3048.             /* Return the file size. */
  3049.  
  3050.         case 1:
  3051.  
  3052.             Size = 0;
  3053.  
  3054.             if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  3055.             {
  3056.                 UBYTE    RealName[MAX_FILENAME_LENGTH];
  3057.                 BPTR    FileLock;
  3058.  
  3059.                 if(OriginalName[0])
  3060.                 {
  3061.                     if(!Stricmp(ShrunkenName,FileName))
  3062.                         FileName = NewFileName(OriginalName,RealName);
  3063.                     else
  3064.                         FileName = NewFileName(FileName,RealName);
  3065.                 }
  3066.                 else
  3067.                     FileName = NewFileName(FileName,RealName);
  3068.  
  3069.                 if(FileLock = Lock(FileName,ACCESS_READ))
  3070.                 {
  3071.                     if(Examine(FileLock,FileInfo))
  3072.                     {
  3073.                         if(FileInfo -> fib_DirEntryType < 0)
  3074.                             Size = FileInfo -> fib_Size;
  3075.                     }
  3076.  
  3077.                     UnLock(FileLock);
  3078.                 }
  3079.  
  3080.                 FreeDosObject(DOS_FIB,FileInfo);
  3081.             }
  3082.  
  3083.             return(Size);
  3084.  
  3085.             /* Return the file transfer mode. */
  3086.  
  3087.         case 2:
  3088.  
  3089.             return(BinaryTransfer ? 1 : 2);
  3090.  
  3091.             /* Ignore the rest. */
  3092.  
  3093.         default:
  3094.  
  3095.             return(0);
  3096.     }
  3097. }
  3098.  
  3099.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  3100.      *
  3101.      *    Provide a more polished user interface to set the
  3102.      *    transfer protocol options.
  3103.      */
  3104.  
  3105. ULONG __saveds __asm
  3106. xpr_options(register __d0 LONG NumOpts,register __a0 struct xpr_option **Opts)
  3107. {
  3108.     DB(kprintf("xpr_options(%ld,0x%08lx)\n",NumOpts,Opts));
  3109.  
  3110.     if(NumOpts && Opts)
  3111.     {
  3112.         enum    {    GAD_USE=1,GAD_CANCEL,GAD_SPECIAL };
  3113.  
  3114.         struct LayoutHandle    *Handle;
  3115.         ULONG                 Flags = NULL;
  3116.  
  3117.             /* We only have 32 bits! */
  3118.  
  3119.         if(NumOpts > 32)
  3120.             NumOpts = 32;
  3121.  
  3122.         if(Handle = LT_CreateHandleTags(Window -> WScreen,
  3123.             LH_LocaleHook,    &LocaleHook,
  3124.         TAG_DONE))
  3125.         {
  3126.             struct Window    *PanelWindow;
  3127.             LONG             i,Split;
  3128.  
  3129.             if(NumOpts > 16)
  3130.                 Split = NumOpts / 2;
  3131.             else
  3132.                 Split = -1;
  3133.  
  3134.             LT_New(Handle,
  3135.                 LA_Type,    VERTICAL_KIND,
  3136.             TAG_DONE);
  3137.             {
  3138.                 LT_New(Handle,
  3139.                     LA_Type,    HORIZONTAL_KIND,
  3140.                     LA_LabelID,    MSG_V36_1501,
  3141.                 TAG_DONE);
  3142.                 {
  3143.                     LT_New(Handle,
  3144.                         LA_Type,    VERTICAL_KIND,
  3145.                     TAG_DONE);
  3146.                     {
  3147.                         for(i = 0 ; i < NumOpts ; i++)
  3148.                         {
  3149.                             if(Opts[i])
  3150.                             {
  3151.                                 switch(Opts[i] -> xpro_type)
  3152.                                 {
  3153.                                     case XPRO_BOOLEAN:
  3154.  
  3155.                                         LT_New(Handle,
  3156.                                             LA_Type,        CHECKBOX_KIND,
  3157.                                             LA_LabelText,    Opts[i] -> xpro_description,
  3158.                                             LA_ID,            GAD_SPECIAL + i,
  3159.                                             GTCB_Checked,    GetOptionMode(Opts[i]),
  3160.                                         TAG_DONE);
  3161.  
  3162.                                         break;
  3163.  
  3164.                                     case XPRO_LONG:
  3165.  
  3166.                                         LT_New(Handle,
  3167.                                             LA_Type,                INTEGER_KIND,
  3168.                                             LA_LabelText,            Opts[i] -> xpro_description,
  3169.                                             LA_ID,                    GAD_SPECIAL + i,
  3170.                                             LA_Chars,                15,
  3171.                                             GTIN_Number,            Atol(Opts[i] -> xpro_value),
  3172.                                             LAIN_UseIncrementers,    TRUE,
  3173.                                         TAG_DONE);
  3174.  
  3175.                                         break;
  3176.  
  3177.                                     case XPRO_STRING:
  3178.  
  3179.                                         LT_New(Handle,
  3180.                                             LA_Type,        STRING_KIND,
  3181.                                             LA_LabelText,    Opts[i] -> xpro_description,
  3182.                                             LA_ID,            GAD_SPECIAL + i,
  3183.                                             LA_Chars,        15,
  3184.                                             GTST_String,    Opts[i] -> xpro_value,
  3185.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  3186.                                         TAG_DONE);
  3187.  
  3188.                                         break;
  3189.  
  3190.                                     case XPRO_COMMPAR:
  3191.  
  3192.                                         LT_New(Handle,
  3193.                                             LA_Type,        STRING_KIND,
  3194.                                             LA_LabelText,    Opts[i] -> xpro_description,
  3195.                                             LA_ID,            GAD_SPECIAL + i,
  3196.                                             LA_Chars,        15,
  3197.                                             LA_HighLabel,    TRUE,
  3198.                                             GTST_String,    Opts[i] -> xpro_value,
  3199.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  3200.                                         TAG_DONE);
  3201.  
  3202.                                         break;
  3203.  
  3204.                                     case XPRO_HEADER:
  3205.  
  3206.                                         LT_New(Handle,
  3207.                                             LA_Type,        TEXT_KIND,
  3208.                                             LA_LabelText,    Opts[i] -> xpro_description,
  3209.                                             LA_HighLabel,    TRUE,
  3210.                                             GTTX_Text,        " ",
  3211.                                         TAG_DONE);
  3212.  
  3213.                                         break;
  3214.  
  3215.                                     case XPRO_COMMAND:
  3216.  
  3217.                                         LT_New(Handle,
  3218.                                             LA_Type,        BUTTON_KIND,
  3219.                                             LA_LabelText,    Opts[i] -> xpro_description,
  3220.                                             LA_ID,            GAD_SPECIAL + i,
  3221.                                             LA_Chars,        15,
  3222.                                         TAG_DONE);
  3223.  
  3224.                                         break;
  3225.                                 }
  3226.                             }
  3227.  
  3228.                             if(i == Split)
  3229.                             {
  3230.                                 LT_EndGroup(Handle);
  3231.  
  3232.                                 LT_New(Handle,
  3233.                                     LA_Type,    VERTICAL_KIND,
  3234.                                 TAG_DONE);
  3235.                             }
  3236.                         }
  3237.  
  3238.                         LT_EndGroup(Handle);
  3239.                     }
  3240.  
  3241.                     LT_EndGroup(Handle);
  3242.                 }
  3243.  
  3244.                 LT_New(Handle,
  3245.                     LA_Type,VERTICAL_KIND,
  3246.                 TAG_DONE);
  3247.                 {
  3248.                     LT_New(Handle,
  3249.                         LA_Type,        XBAR_KIND,
  3250.                         LAXB_FullSize,    TRUE,
  3251.                     TAG_DONE);
  3252.  
  3253.                     LT_EndGroup(Handle);
  3254.                 }
  3255.  
  3256.                 LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  3257.                     LAGR_SameSize,        TRUE,
  3258.                     LAGR_Spread,        TRUE,
  3259.                 TAG_DONE);
  3260.                 {
  3261.                     LT_New(Handle,
  3262.                         LA_Type,        BUTTON_KIND,
  3263.                         LA_LabelID,        MSG_GLOBAL_USE_GAD,
  3264.                         LA_ID,            GAD_USE,
  3265.                         LABT_ReturnKey,    TRUE,
  3266.                         LABT_ExtraFat,    TRUE,
  3267.                     TAG_DONE);
  3268.  
  3269.                     LT_New(Handle,
  3270.                         LA_Type,        BUTTON_KIND,
  3271.                         LA_LabelID,        MSG_GLOBAL_CANCEL_GAD,
  3272.                         LA_ID,            GAD_CANCEL,
  3273.                         LABT_EscKey,    TRUE,
  3274.                         LABT_ExtraFat,    TRUE,
  3275.                     TAG_DONE);
  3276.  
  3277.                     LT_EndGroup(Handle);
  3278.                 }
  3279.  
  3280.                 LT_EndGroup(Handle);
  3281.             }
  3282.  
  3283.             if(PanelWindow = LT_Build(Handle,
  3284.                 LAWN_TitleText,        OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),
  3285.                 LAWN_IDCMP,            IDCMP_CLOSEWINDOW,
  3286.                 LAWN_HelpHook,        &GuideHook,
  3287.                 LAWN_Parent,        Window,
  3288.                 WA_DepthGadget,        TRUE,
  3289.                 WA_CloseGadget,        TRUE,
  3290.                 WA_DragBar,            TRUE,
  3291.                 WA_RMBTrap,            TRUE,
  3292.                 WA_Activate,        TRUE,
  3293.                 WA_SimpleRefresh,    TRUE,
  3294.             TAG_DONE))
  3295.             {
  3296.                 struct IntuiMessage    *Message;
  3297.                 BOOLEAN                 Done = FALSE;
  3298.                 ULONG                 MsgClass;
  3299.                 UWORD                 MsgCode;
  3300.                 struct Gadget        *MsgGadget;
  3301.                 BOOLEAN                 CheckFlags = FALSE;
  3302.  
  3303.                 PushWindow(PanelWindow);
  3304.  
  3305.                 LT_ShowWindow(Handle,TRUE);
  3306.  
  3307.                 do
  3308.                 {
  3309.                     if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  3310.                         break;
  3311.  
  3312.                     while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
  3313.                     {
  3314.                         MsgClass        = Message -> Class;
  3315.                         MsgCode            = Message -> Code;
  3316.                         MsgGadget        = (struct Gadget *)Message -> IAddress;
  3317.  
  3318.                         LT_ReplyIMsg(Message);
  3319.  
  3320.                         if(MsgClass == IDCMP_CLOSEWINDOW)
  3321.                             Done = TRUE;
  3322.  
  3323.                         if(MsgClass == IDCMP_GADGETUP)
  3324.                         {
  3325.                             switch(MsgGadget -> GadgetID)
  3326.                             {
  3327.                                 case GAD_USE:
  3328.  
  3329.                                     Done = CheckFlags = TRUE;
  3330.                                     break;
  3331.  
  3332.                                 case GAD_CANCEL:
  3333.  
  3334.                                     Done = TRUE;
  3335.                                     break;
  3336.  
  3337.                                 default:
  3338.  
  3339.                                     if(MsgGadget -> GadgetID - GAD_SPECIAL < NumOpts)
  3340.                                     {
  3341.                                         i = MsgGadget -> GadgetID - GAD_SPECIAL;
  3342.  
  3343.                                         if(Opts[i] -> xpro_type == XPRO_COMMAND || (Opts[i] -> xpro_type == XPRO_COMMPAR && MsgCode != '\t'))
  3344.                                         {
  3345.                                             Flags = (1L << i);
  3346.  
  3347.                                             XPRCommandSelected = Done = CheckFlags = TRUE;
  3348.                                         }
  3349.                                     }
  3350.  
  3351.                                     break;
  3352.                             }
  3353.                         }
  3354.                     }
  3355.                 }
  3356.                 while(!Done);
  3357.  
  3358.                 PopWindow();
  3359.  
  3360.                 if(CheckFlags)
  3361.                 {
  3362.                     LT_LockWindow(PanelWindow);
  3363.  
  3364.                     for(i = 0 ; i < NumOpts ; i++)
  3365.                     {
  3366.                         if(Opts[i])
  3367.                         {
  3368.                             switch(Opts[i] -> xpro_type)
  3369.                             {
  3370.                                 case XPRO_BOOLEAN:
  3371.  
  3372.                                     if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE) != GetOptionMode(Opts[i]))
  3373.                                     {
  3374.                                         Flags |= (1L << i);
  3375.  
  3376.                                         if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  3377.                                             strcpy(Opts[i] -> xpro_value,"yes");
  3378.                                         else
  3379.                                             strcpy(Opts[i] -> xpro_value,"no");
  3380.  
  3381.                                         NewOptions = TRUE;
  3382.                                     }
  3383.  
  3384.                                     break;
  3385.  
  3386.                                 case XPRO_LONG:
  3387.  
  3388.                                     if(Atol(Opts[i] -> xpro_value) != LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  3389.                                     {
  3390.                                         Flags |= (1L << i);
  3391.  
  3392.                                         SPrintf(Opts[i] -> xpro_value,"%ld",LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  3393.  
  3394.                                         NewOptions = TRUE;
  3395.                                     }
  3396.  
  3397.                                     break;
  3398.  
  3399.                                 case XPRO_STRING:
  3400.  
  3401.                                     if(strcmp(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE)))
  3402.                                     {
  3403.                                         Flags |= (1L << i);
  3404.  
  3405.                                         strcpy(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  3406.  
  3407.                                         NewOptions = TRUE;
  3408.                                     }
  3409.  
  3410.                                     break;
  3411.                             }
  3412.                         }
  3413.                     }
  3414.  
  3415.                     LT_UnlockWindow(PanelWindow);
  3416.                 }
  3417.                 else
  3418.                     Flags = NULL;
  3419.             }
  3420.  
  3421.             LT_DeleteHandle(Handle);
  3422.         }
  3423.  
  3424.         return(Flags);
  3425.     }
  3426.     else
  3427.         return(NULL);
  3428. }
  3429.  
  3430.     /* xpr_unlink(STRPTR FileName):
  3431.      *
  3432.      *    Remove (delete) a given file.
  3433.      */
  3434.  
  3435. LONG __saveds __asm
  3436. xpr_unlink(register __a0 STRPTR FileName)
  3437. {
  3438.     DB(kprintf("xpr_unlink(\"%s\")\n",FileName));
  3439.  
  3440.         /* Sorry, but it is far too dangerous to let the protocol
  3441.          * remove any files with path name substitution enabled.
  3442.          * The protocol could accidentally hit the wrong file.
  3443.          */
  3444.  
  3445.     if(!Config -> TransferConfig -> OverridePath)
  3446.     {
  3447.         if(OriginalName[0])
  3448.         {
  3449.             if(!Stricmp(ShrunkenName,FileName))
  3450.                 FileName = OriginalName;
  3451.         }
  3452.  
  3453.         if(DeleteFile(FileName))
  3454.         {
  3455.             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FilePart(FileName));
  3456.  
  3457.             return(0);
  3458.         }
  3459.     }
  3460.  
  3461.     return(-1);
  3462. }
  3463.  
  3464.     /* xpr_squery():
  3465.      *
  3466.      *    Check how many characters are present in the serial buffer.
  3467.      */
  3468.  
  3469. LONG __saveds __asm
  3470. xpr_squery()
  3471. {
  3472.     ULONG    Waiting;
  3473.     UWORD    Status;
  3474.  
  3475.     DB(kprintf("xpr_squery()\n"));
  3476.  
  3477.     GetSerialInfo(&Waiting,&Status);
  3478.  
  3479.         /* Return error if carrier is lost. */
  3480.  
  3481.     if((Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  3482.     {
  3483.         if(!CarrierMessage)
  3484.         {
  3485.             CarrierMessage = TRUE;
  3486.  
  3487.             AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  3488.         }
  3489.  
  3490.         ObtainSemaphore(&OnlineSemaphore);
  3491.  
  3492.         if(Online)
  3493.         {
  3494.             WasOnline    = Online;
  3495.             Online        = FALSE;
  3496.         }
  3497.  
  3498.         ReleaseSemaphore(&OnlineSemaphore);
  3499.  
  3500.         TransferError = TRUE;
  3501.     }
  3502.     else
  3503.         return((LONG)Waiting);
  3504. }
  3505.  
  3506.     /* xpr_getptr(LONG InfoType):
  3507.      *
  3508.      *    Return a pointer to the term custom screen.
  3509.      */
  3510.  
  3511. LONG __saveds __asm
  3512. xpr_getptr(register __d0 LONG InfoType)
  3513. {
  3514.     DB(kprintf("xpr_getptr(%ld)\n",InfoType));
  3515.  
  3516.     if(InfoType == 1)
  3517.         return((LONG)Window -> WScreen);
  3518.     else
  3519.         return(-1);
  3520. }
  3521.  
  3522.     /* xpr_stealopts(STRPTR Prompt,STRPTR Buffer):
  3523.      *
  3524.      *    Steal the contents of the options buffer (replacement
  3525.      *    for xpr_gets).
  3526.      */
  3527.  
  3528. LONG __saveds __asm
  3529. xpr_stealopts(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  3530. {
  3531.     DB(kprintf("xpr_stealopts(\"%s\",\"%s\")\n",Prompt,Buffer));
  3532.  
  3533.     if(Buffer)
  3534.         strcpy(ProtocolOptsBuffer,Buffer);
  3535.  
  3536.     return(1);
  3537. }
  3538.